├── run.log ├── .gitignore ├── requirements.txt ├── docs ├── favicon.ico ├── demo │ └── README.md ├── _coverpage.md ├── show │ ├── up.md │ ├── wechat.md │ └── count.md ├── log │ └── README.md ├── statement │ └── README.md ├── api │ ├── README.md │ ├── remix.md │ ├── server.md │ └── github.md ├── python │ ├── local.md │ ├── server.md │ └── cloud.md ├── _sidebar.md ├── attention │ └── README.md ├── README.md ├── structure │ └── README.md ├── download │ └── README.md ├── index.html ├── question │ └── README.md ├── document │ └── README.md ├── sw.js └── config │ └── README.md ├── image-20220516134035852.png ├── image-20220516134054150.png ├── Dockerfile ├── account.json ├── compose ├── docker-compose.yml └── init.config ├── LICENSE ├── README.md ├── init.config ├── index.py └── main.py /run.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | run.log -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.20.0 2 | 3 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trulymust/neteasy_music_sign/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /image-20220516134035852.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trulymust/neteasy_music_sign/HEAD/image-20220516134035852.png -------------------------------------------------------------------------------- /image-20220516134054150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trulymust/neteasy_music_sign/HEAD/image-20220516134054150.png -------------------------------------------------------------------------------- /docs/demo/README.md: -------------------------------------------------------------------------------- 1 | # API接口列表 2 | 3 | !> 本项目提供的线上 demo均来自网友捐赠,目的在于为不方便搭建API的用户提供便利,但目前有网友反馈接口被滥用导致进了网易黑名单,故暂时不再提供相关API,后续解决办法可能会使用云函数搭建。 4 | 5 | ?>最后再次感谢为项目做出贡献的每一位,决定项目生态的不是代码,而是每一个参与者,感谢大家! -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 网易云升级全家桶 4 | 5 | 一个用于网易云音乐快速满级的服务。 6 | 7 | - 每天自动升级 8 | - 任务进度推送到微信 9 | - 自定义网易云日推风格 10 | 11 | [GitHub](https://github.com/ZainCheung/netease-cloud/) [Get Started](#首页) -------------------------------------------------------------------------------- /docs/show/up.md: -------------------------------------------------------------------------------- 1 | # 账号升级 2 | 3 | 使用前可以看到是**9027**首 4 | 5 | ![使用前](https://s1.ax1x.com/2020/06/27/N6YGQg.png) 6 | 7 | 使用后是**9327**首,刚好涨了300首 8 | 9 | ![使用后](https://s1.ax1x.com/2020/06/27/N6tWuQ.png) 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/log/README.md: -------------------------------------------------------------------------------- 1 | # 查看日志 2 | 3 | 只有本地部署和服务器部署才会生成日志文件,而用云函数搭建的不会有这个`run.log`文件,如需查看日志可以查看云函数内置的日志。 4 | 5 | 日志文件记录了程序运行的状况,程序运行中生成的所有记录都会保存在日志文件中,第一次克隆项目时,不会看到`run.log`日志文件,而在程序第一次运行时才会生成,下面看一下我在服务器上的日志: 6 | 7 | ![日志](https://s1.ax1x.com/2020/07/15/UdnjMt.png) 8 | -------------------------------------------------------------------------------- /docs/show/wechat.md: -------------------------------------------------------------------------------- 1 | # 微信提醒 2 | 3 | 推送方式共三种,分别是Server免费版、Server订阅版、WxPusher推送,需要自己提前申请对应平台的密钥以及做好绑定微信的准备工作。需要切换推送方式则可以查看文档中的设置章节。 4 | 5 | 推送的内容也可以自行修改,`main.py`文件(云函数用户更改`index.py`)的`diyText`函数里的content为提示内容,里面可以自定义提示内容,如有需要自己动手DIY。 6 | 7 | 新版效果待更新。 8 | 9 | ------ 10 | 11 | -------------------------------------------------------------------------------- /docs/statement/README.md: -------------------------------------------------------------------------------- 1 | # 免责声明 2 | 3 | 请不要找其他人代挂账号,不要向他人透露自己的账号密码信息,如果使用项目默认的api请使用md5摘要密码,本项目的所有脚本以及软件仅用于个人学习开发测试,我们不保证功能的实时性和可行性,通过使用本项目随之而来的风险与本项目无关,所有`网易云`相关字样版权属于网易公司,勿用于商业及非法用途,如产生法律纠纷与本项目无关。 4 | 5 | 如果您喜欢网易云音乐,请支持官方渠道,共建生态,以便得到更好的服务。 6 | 7 | 如果该项目侵犯了你的利益,携带**权利证明**请发送邮箱到 ZainCheung@qq.com,我们会很快的为您处理。 -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-slim 2 | MAINTAINER Sage (sagelovemio@qq.com) 3 | 4 | WORKDIR /app 5 | COPY requirements.txt run.log ./ 6 | RUN ln -sf /dev/stdout /app/run.log 7 | RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt 8 | 9 | COPY main.py ./ 10 | CMD ["python", "main.py"] -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | # 部署接口 2 | 3 | 建议新手使用自动托管方式,可以完全不需要编程基础即可搭建api接口,推荐使用网站:[https://glitch.com/](https://glitch.com/) 4 | 5 | 这个网站是国外的,名气也很大,在上面托管网站的有几百万,免费使用,缺点就是速度没有国内的服务器快,还有就是如果没有访问了,一定时间后会进入休眠,等待下一次请求到来后需要等待几秒的解冻时间。不过这些对这个项目并没有什么影响,所以可以放心部署。 6 | 7 | API项目地址:[https://github.com/ZainCheung/netease-cloud-api](https://github.com/ZainCheung/netease-cloud-api) 8 | 9 | 下面三种方法,第一种第二种最简单但速度慢,而且需要你有网站账号,第三种访问速度快但需要你有服务器,大家自己取舍,但基本上有服务器了都想自己搭建吧,大家随意 -------------------------------------------------------------------------------- /account.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "countrycode": 86, 4 | "account": "ZainCheung@163.com", 5 | "password": "10ca5e4c316f81c5d9b56702********", 6 | "al_id": 12345678, 7 | "sckey": "SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9********", 8 | "pushmethod": "", 9 | "appToken": "", 10 | "wxpusheruid": "", 11 | "barkServer": "https://api.day.app", 12 | "barkKey": "" 13 | } 14 | ] -------------------------------------------------------------------------------- /docs/api/remix.md: -------------------------------------------------------------------------------- 1 | ## 直接复制项目 {docsify-ignore-all} 2 | 3 | 或者可以直接复制一份这个API项目成为你的项目,进入开发者的api服务器: https://glitch.com/edit/#!/netease-cloud-api-sep 选择右上角的 `Remix to Exit`,即可成为你自己的项目,你便可以对代码进行修改,自定义你的域名。 4 | 5 | ![](https://s1.ax1x.com/2020/06/29/NWTJcn.png) 6 | 7 | ##### 获得API地址 8 | 9 | ![](https://s1.ax1x.com/2020/07/02/Nb1c1e.png) 10 | 11 | ##### 又或者 12 | 13 | ![](https://s1.ax1x.com/2020/07/02/Nb1WnA.png) 14 | 15 | 访问你的接口看到欢迎页面即部署成功 16 | 17 | ![](https://s1.ax1x.com/2020/06/29/NWIt8s.png) -------------------------------------------------------------------------------- /docs/python/local.md: -------------------------------------------------------------------------------- 1 | ## 本地使用 {docsify-ignore-all} 2 | 3 | > 本地部署需要电脑下载并**安装配置好Python** 4 | 5 | ### 1. 下载项目 6 | 7 | 克隆项目到本地 8 | 9 | ```bash 10 | git clone https://github.com/ZainCheung/netease-cloud.git 11 | ``` 12 | 13 | 或者fork本项目到你的仓库进行克隆 14 | 15 | 又或者在项目仓库直接下载ZIP压缩包,这些都是可以的 16 | 17 | ### 2. 安装依赖 18 | 19 | > 需要安装的依赖目前只有一个`request`,如果运行报错缺少什么模块就给什么模块加进`requirements.txt`中 20 | 21 | ```bash 22 | pip install -r requirements.txt 23 | ``` 24 | 25 | ### 3. 配置账号见后文 26 | 27 | ### 4. 启动程序 28 | 29 | > 程序需要`python3`的运行环境,如果没有请自行下载安装配置,,启动程序前一定要先配置账号,然后再启动程序 30 | 31 | ``` 32 | python main.py 33 | ``` 34 | 35 | ------ 36 | 37 | -------------------------------------------------------------------------------- /docs/python/server.md: -------------------------------------------------------------------------------- 1 | ## 服务器部署 {docsify-ignore-all} 2 | 3 | 推荐使用宝塔面板,在宝塔应用商店里面有一个Python项目管理器,下载安装,并选择3.0以上版本,推荐3.7.2版本. 4 | 5 | ### 1. 下载安装Python项目管理器 6 | 7 | ![](https://s1.ax1x.com/2020/06/28/Ngr2K1.png) 8 | 9 | ### 2. 新建项目 10 | 11 | > 这里的netease-cloud就是这个项目的文件夹,我给放在了/www/wwwroot/路径下了,可见我这里下载安装的是3.7.2版本的python框架选择Python,启动方式也为Python,启动文件选择`main.py`端口不用填,勾选安装模块依赖,是否要开机启动自己随意咯,然后确定。 12 | 13 | ![](https://s1.ax1x.com/2020/06/28/Ng6lE6.png) 14 | 15 | ![](https://s1.ax1x.com/2020/06/28/NgsKz9.png) 16 | 17 | ### 3. 确定运行状态 18 | 19 | ![](https://s1.ax1x.com/2020/06/28/Ng6egJ.png) 20 | 21 | 这时候项目就开始在运行了,就可以去项目在文件夹的路径,找到`run.log`即可查看运行日志 22 | 23 | 部署前也要记得先配置,然后再部署 -------------------------------------------------------------------------------- /docs/show/count.md: -------------------------------------------------------------------------------- 1 | # 播放次数 2 | 3 | 使用前可以看到两首歌分别是**92**次和**41**次 4 | 5 | ![使用前](https://s1.ax1x.com/2020/07/08/UZyQv8.png) 6 | 7 | 使用后两首各自涨了**300**首 8 | 9 | ![使用后](https://s1.ax1x.com/2020/07/08/UZyUCq.png) 10 | 11 | 如果没有立刻变化,那么在右上角切换到所有时间即可 12 | 13 | ![](https://s1.ax1x.com/2020/07/11/UQfyI1.png) 14 | 15 | 有人可能会问上面那个累计播放次数**2218**首没有变化,那是因为总数的累计播放只计算不重复的歌曲。 16 | 17 | 调用的API地址是(这个API可以自己搭建): 18 | 19 | ![](https://s1.ax1x.com/2020/07/08/UZ6geg.png) 20 | 21 | 打开软件填好账号密码(**MD5**)和**API**就可以开始执行任务了 22 | 23 | 软件的截图是这样 24 | 25 | ![](https://s1.ax1x.com/2020/07/11/UloH6P.png) 26 | 27 | 这个歌单的`id`为`5101628912`,一共有6首歌,播放次数填写为`1000`,点击开始执行后等待几秒钟便可以在软件下方的状态栏看到反馈,这里一共听了6000首。 -------------------------------------------------------------------------------- /docs/api/server.md: -------------------------------------------------------------------------------- 1 | ## 服务器部署 {docsify-ignore-all} 2 | 3 | 部署到服务器,对于新手还是比较建议安装宝塔面板,然后就可以在浏览器中进行界面化操作,免得有的人不会Linux的命令行。 4 | 5 | #### 1. 下载PHP 6 | 7 | 确保下载了PHP,版本不要太老就行 8 | 9 | ![](https://s1.ax1x.com/2020/06/29/NWh7Ps.png) 10 | 11 | #### 2. 添加网站 12 | 13 | 填入你提前在你的域名运营商解析的域名,可以是子域名比如,api.xxxxxx.com,写个网站备注,然后根目录选择到下载的项目路径,FTP不创建,数据库不创建默认utf-8就行,程序类型PHP,版本选择下载的版本,提交即可运行你的网站. 14 | 15 | ![](https://s1.ax1x.com/2020/06/29/NWhza4.png) 16 | 17 | ![](https://s1.ax1x.com/2020/06/29/NW4Ydg.png) 18 | 19 | #### 3. 运行网站 20 | 21 | 这里演示域名为test.com,然后在浏览器里输入你的网站地址,看到欢迎页面即为部署成功 22 | 23 | ![](https://s1.ax1x.com/2020/06/29/NW4hS1.png) 24 | 25 | ![](https://s1.ax1x.com/2020/06/29/NWIt8s.png) -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * [首页](/ "网易云升级服务") 4 | * 部署项目 5 | * * [云函数](python/cloud "使用云函数部署") 6 | * * [服务器](python/server "使用云函数部署") 7 | * * [本地使用](python/local "本地部署") 8 | * [部署接口](api/ "API接口的使用") 9 | * * [GitHub](api/github "使用GitHub部署API") 10 | * * [复制服务](api/remix "使用Glitch的remix部署API") 11 | * * [服务器](api/server "使用服务器部署API") 12 | * 效果演示 13 | * * [账号升级](show/up "账号升级页面演示") 14 | * * [微信提醒](show/wechat "微信推送消息") 15 | * * [播放次数](show/count "刷单曲播放次数") 16 | * [项目配置](config/) 17 | * [API接口案例](demo/) 18 | * [接口文档](document/) 19 | * [下载地址](download/) 20 | * [查看日志](log/) 21 | * [注意事项](attention/) 22 | * [常见问题](question/) 23 | * [项目结构](structure/) 24 | * [免责声明](statement/) -------------------------------------------------------------------------------- /compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | # 网易云API 4 | service-musicapi: 5 | container_name: service-musicapi 6 | hostname: service-musicapi 7 | image: binaryify/netease_cloud_music_api:v4.8.7 8 | restart: unless-stopped 9 | volumes: 10 | - /etc/localtime:/etc/localtime 11 | - /etc/timezone:/etc/timezone 12 | 13 | # 网易云每日打卡 14 | service-musicsign: 15 | container_name: service-musicsign 16 | hostname: service-musicsign 17 | image: sage668/neteasy_music_sign:latest 18 | restart: unless-stopped 19 | depends_on: 20 | - service-musicapi 21 | volumes: 22 | - ./init.config:/app/init.config 23 | - /etc/localtime:/etc/localtime 24 | - /etc/timezone:/etc/timezone -------------------------------------------------------------------------------- /docs/api/github.md: -------------------------------------------------------------------------------- 1 | ## 从GitHub导入项目 {docsify-ignore-all} 2 | 3 | 使用这种方式部署网站接口,0成本且快速可用,且不用担心环境部署运维等问题,当然如果有条件用自己的服务器搭建也是可以的。 4 | 5 | #### 1. fork项目 6 | 7 | fork这个API项目到你的仓库,记得点个Star哦 8 | 9 | ![](https://s1.ax1x.com/2020/08/05/as0qZ8.png) 10 | 11 | #### 2. 导入项目 12 | 13 | 打开网站注册并登陆,新建项目,选择从GitHub导入,填入你的的git地址,地址在你的Github项目的clone按钮里,要用https 14 | 15 | ![](https://s1.ax1x.com/2020/06/29/NWo8L6.png) 16 | 17 | #### 3. 修改项目名 18 | 19 | 修改你的glitch项目名,例如:netease-test 20 | 21 | ![](https://s1.ax1x.com/2020/06/29/NWocTS.png) 22 | 23 | ------ 24 | 25 | #### 4. 得到API地址 26 | 27 | 你的接口名为“项目名.glitch.com”,例如:https://netease-test.glitch.me/ 28 | 29 | ![](https://s1.ax1x.com/2020/07/02/Nb1c1e.png) 30 | 31 | ##### 又或者 32 | 33 | ![](https://s1.ax1x.com/2020/07/02/Nb1WnA.png) 34 | 35 | 访问你的接口看到欢迎页面即部署成功 36 | 37 | ![](https://s1.ax1x.com/2020/06/29/NWIt8s.png) -------------------------------------------------------------------------------- /docs/attention/README.md: -------------------------------------------------------------------------------- 1 | # 注意事项 2 | 3 | ### Server酱 4 | 5 | 一定要绑定微信才会有效果 6 | 7 | Server酱的官网地址:[http://sc.ftqq.com/](http://sc.ftqq.com/) 8 | 9 | ### MD5 10 | 11 | **制作时选择32位小写!!!** 12 | 13 | 在线“制作”MD5:[https://tool.chinaz.com/tools/md5.aspx](https://tool.chinaz.com/tools/md5.aspx) 14 | 15 | 比较建议大家使用MD5,因为别人即使知道了你的MD5,也很难还原你的密码,相对而言要安全很多,而原密码在你制作MD5时就被隐藏起来了,只有你一个人知道密码 16 | 17 | ### 修改听歌次数 18 | 19 | 注意:云函数修改`index.py`,服务器或者本地的话则是修改`main.py` 20 | 21 | 如果你的等级比较高,然后使用这个发现每次都没有听满300首,那么你可以修改主程序的`start`函数(165行左右)的打卡次数,将3改大点,比如改到6就可以打卡6次 22 | 23 | ```python 24 | for i in range(1,3): 25 | ``` 26 | 27 | 如果你嫌打卡速度慢了,可以修改休眠时间,30秒改为10秒之类的,请自行调试 28 | 29 | ```python 30 | time.sleep(30) 31 | ``` 32 | 33 | ### 可用性 34 | 35 | 可能有人会说,直接使用网页或者电脑程序每天打卡不就好了,干嘛还要脚本。是的,使用网站和程序确实可以做到一样的效果,不过我懒啊,还总是忘事,所以就让它彻底全自动化,可能也有不少人愿意像我这样折腾一番,然后就可以坐享其成一劳永逸,每天坐等微信提醒就行。 36 | 37 | ### 初衷 38 | 39 | 使用网易云也有挺久了,听的歌也挺多,但总是会听重复的歌,而重复的歌又不算进等级里去,所以还是很想升级的。 -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # 网易云音乐升级全家桶 2 | 3 |

4 | Author 5 | PHP 6 | 7 |

8 | 通过调用官方接口,每天自动刷完300首歌,借此可以达到快速升级的目的。 9 | 10 | 一个账号平均耗时为1分钟左右。放在服务器运行即可不需要人工干预,支持无服务器的云函数部署,每天自动听歌做任务,向你的微信发送任务通知。 11 | 12 | ------ 13 | 14 | 目前已实现功能: 15 | 16 | 17 | - [x] 每天自动升级 18 | - [x] 任务进度推送到微信 19 | - [x] 自定义网易云日推风格 20 | 21 | 本项目实则由三个项目组成,分别是: 22 | 23 | ?>给账号升级的Python项目:[netease-cloud](https://github.com/ZainCheung/netease-cloud) 24 | 25 | ?>使用PHP搭建的API接口:[netease-cloud-api](https://github.com/ZainCheung/netease-cloud-api) 26 | 27 | ?>使用Python开发的修改日推(每日推荐歌曲)Windows软件:[netease-cloud-fast](https://github.com/ZainCheung/netease-cloud-fastplay) -------------------------------------------------------------------------------- /docs/structure/README.md: -------------------------------------------------------------------------------- 1 | # 项目结构 2 | 3 | 4 | 5 | ## netease-cloud 6 | 7 | ``` 8 | |-- 项目文件夹 9 | |-- LICENSE 10 | |-- README.md 11 | |-- account.json 12 | |-- init.config 13 | |-- main.py 14 | |-- requirements.txt 15 | |-- run.log 16 | ``` 17 | 18 | `LICENSE`:开源许可证 19 | 20 | `README.md`:项目自述文件 21 | 22 | `account.json`:账号存放文件 23 | 24 | `init.config`:配置文件 25 | 26 | `main.py`:主程序 27 | 28 | `requirements.txt`:依赖清单 29 | 30 | `run.log`:运行日志 31 | 32 | 33 | 34 | ## netease-cloud-fastplay 35 | 36 | ``` 37 | |-- 项目文件夹 38 | |-- LICENSE 39 | |-- README.md 40 | |-- init.config 41 | |-- main.py 42 | |-- ui.py 43 | |-- api.py 44 | |-- requirements.txt 45 | |-- run.log 46 | ``` 47 | 48 | `LICENSE`:开源许可证 49 | 50 | `README.md`:项目自述文件 51 | 52 | `init.config`:配置文件 53 | 54 | `main.py`:主程序 55 | 56 | `ui.py`:界面模块 57 | 58 | `api.py`:接口模块 59 | 60 | `requirements.txt`:依赖清单 61 | 62 | `run.log`:运行日志 -------------------------------------------------------------------------------- /docs/download/README.md: -------------------------------------------------------------------------------- 1 | # 下载地址 {docsify-ignore-all} 2 | 3 | 4 | 5 | ## netease-cloud(升级服务) 6 | 7 | 项目地址:[https://github.com/ZainCheung/netease-cloud](https://github.com/ZainCheung/netease-cloud) 8 | 9 | 10 | 11 | ## netease-cloud-api(API接口) 12 | 13 | api接口项目地址:[https://github.com/ZainCheung/netease-cloud-api](https://github.com/ZainCheung/netease-cloud-api) 14 | 15 | api的Demo演示地址:[https://netease-cloud-api-sep.glitch.me/](https://netease-cloud-api-sep.glitch.me/) 16 | 17 | api的Glitch在线服务器:[https://glitch.com/edit/#!/netease-cloud-api-sep](https://glitch.com/edit/#!/netease-cloud-api-sep) 18 | 19 | 20 | 21 | ## netease-cloud-fastplay(快速刷歌) 22 | 23 | 项目地址:[https://github.com/ZainCheung/netease-cloud-fastplay](https://github.com/ZainCheung/netease-cloud-fastplay) 24 | 25 | 软件下载地址(蓝奏云):[https://zaincheung.lanzous.com/i9HD9ehj29g](https://zaincheung.lanzous.com/i9HD9ehj29g) 26 | 27 | 软件下载地址(天翼云):https://cloud.189.cn/t/2mERFjiiUj2u (访问码:fd6v) 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Zain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 网易云音乐自动听歌打卡,直冲LV10 2 | 3 | ​ 本项目基于[GayHub上的项目](https://github.com/ZainCheung/netease-cloud),在此感谢原作者的付出,因为本人下载后发现不能正常使用,因此在原作上基础上修改了部分BUG,适配了网易云的最新API,使打卡功能可正常使用。 4 | 5 | 6 | 7 | ## 项目主要文件说明 8 | 9 | account.json 开启多账号功能,此处存放多个账号信息 10 | 11 | init.config 项目配置文件,使用时必须填写配置文件相关参数 12 | 13 | main.py 项目主文件 14 | 15 | requirements.txt 项目依赖库 16 | 17 | run.log 项目日志文件 18 | 19 | 20 | 21 | ## 使用方法 22 | 23 | **使用前必须先部署[NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi),部署完成后将部署地址填入init.config文件中的api字段内。** 24 | 25 | `pip install -r requirements.txt #完成项目依赖安装` **运行过程中若提示缺少依赖,请自行安装** 26 | 27 | 打开init.config文件填写自己的账号密码。**注意:密码明文即可,不要加密,md5Switch保持false不要更改** 28 | 29 | 打开网易云音乐选择一个歌曲数量大于300首的歌单(网易API规定每天打卡上限为300首,所以程序到300首后会自动停止),歌单id获取方法为:选择歌单以链接的形式分享,链接中id=后的一串数字即为歌单id 30 | 31 | `python main.py #运行程序` 32 | 33 | 34 | 35 | ## 说明&截图 36 | 37 | **本项目仅供学习交流使用,若发现BUG或有新的需求请提issues,我看到后会及时处理,若感觉本项目对您有帮助请给一颗star,谢谢。** 38 | 39 | ![](image-20220516134035852.png) 40 | 41 | ![](image-20220516134054150.png) 42 | 43 | ![image](https://user-images.githubusercontent.com/55483183/170169065-dfebedca-1667-4b55-9c1a-c5639f862732.png) 44 | 45 | 46 | 47 | 48 | Test Push -------------------------------------------------------------------------------- /docs/python/cloud.md: -------------------------------------------------------------------------------- 1 | ## 云函数 {docsify-ignore-all} 2 | 3 | **全民升级时代来了!项目支持了云函数!!!** 4 | 5 | 什么是**云函数**?就是可以让你没有服务器、本地电脑不用下载Python也可以使用这个项目,而且还是**白嫖**! 6 | 7 | 既解决了很多人部署的麻烦,也给了那些被劝退的朋友回来的勇气,**十分钟**便可以全部弄完。 8 | 9 | ### 1. 进入云函数 10 | 11 | 这里拿腾讯云的云函数做个案例,没有的可以免费开通一下,地址:[https://console.cloud.tencent.com/scf/list-create?rid=1&ns=default](https://console.cloud.tencent.com/scf/list-create?rid=1&ns=default) 12 | 13 | ### 2. 新建函数 14 | 15 | 函数名随意,运行环境选**Python 3.6**,创建空白函数,然后下一步 16 | 17 | ![新建函数](https://s1.ax1x.com/2020/06/29/Nhgyod.png) 18 | 19 | ### 3. 上传代码 20 | 21 | 确保环境为python 3.6,执行方法改为:`index.main`,提交方式一定要选本地文件夹,然后从GitHub项目克隆Zip压缩包,解压成文件夹,然后点击这个上传把文件夹上传进来,完了后点击下面的高级设置。 22 | 23 | ![](https://s1.ax1x.com/2020/06/29/NhWswF.png) 24 | 25 | ### 4. 高级设置 26 | 27 | 内存用不了太大,**64MB**就够了,超时时间改为最大的**900秒**,然后点击最下面的完成。 28 | 29 | ![](https://s1.ax1x.com/2020/06/29/Nh251x.png) 30 | 31 | ### 5. 配置账号 32 | 33 | 自己改下`init.config`里的账号密码以及Server酱密匙,用到多账号的也要配置`account.json`,做完后点击保存并测试。如果你的配置没有错,稍等几分钟便可以看到结果,在此期间不要刷新页面。结果会在自行日志里。 34 | 35 | ![](https://s1.ax1x.com/2020/06/29/NhR62t.png) 36 | 37 | ### 6. 设置定时 38 | 39 | 点击左边的触发管理,然后新建触发器,触发周期为自定义,表达式就是每天的什么时候做任务,我选择的早上8点30分,可以自行修改,填好后点击提交即可,到此你的每日听歌项目便部署完成,感谢使用!! 40 | 41 | ![](https://s1.ax1x.com/2020/06/29/NhWZIH.png) -------------------------------------------------------------------------------- /init.config: -------------------------------------------------------------------------------- 1 | # setting.config(UTF-8) 2 | 3 | [token] 4 | # 网易云音乐账号(手机号) 5 | account = 6 | 7 | # 密码,明文,请直接输入明文,不需要加密,下方md5Switch请选择false,true会造成二次加密 8 | password = 9 | 10 | # 国家码,用于国外手机号登陆,国内为86 11 | countrycode = 12 | 13 | # 歌单id,请自行选择一个歌曲数量大于300的歌单,歌单id获取方式查看readme 14 | al_id = 123456 15 | 16 | 17 | [setting] 18 | # 接口API,开关的选项只有 True 和 False 19 | # 如需使用本项目还请自行部署API,地址:https://github.com/ZainCheung/netease-cloud-api 20 | api = http://localhost:3000/ 21 | 22 | # 该项不要更改,保持false即可 23 | md5Switch = false 24 | 25 | # 是否开启多账号功能,如果打开将会忽视配置文件里的账号而从account.json中寻找账号信息 26 | # 如果选择使用多账号,请配置好account里的账号和密码,即account和password,而sckey不是必需的,如果为空则不会进行微信推送 27 | # 介于账号安全着想,account.json中的密码必须填写md5加密过的,请不要向他人透露自己的明文密码 28 | peopleSwitch = true 29 | 30 | # 推送方式选择 31 | # 可选参数wxpusher、SCTurbo或留空 32 | # wxpusher: 使用 WxPusher 推送 33 | # SCTurbo: 使用 Server酱Turbo版 推送 34 | # Bark: 使用 Bark 推送 35 | # 留空:使用 Server酱免费版 推送或不推送 36 | pushmethod = 37 | 38 | # Server酱的密匙,不需要推送就留空 39 | # 免费版密匙的免费申请参考:http://sc.ftqq.com/ 40 | # Turbo版的密钥获取:https://sct.ftqq.com/sendkey 41 | # 免费版和Turbo版的密钥长度不一样,请注意检查,不可混用 42 | sckey = SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9******** 43 | 44 | # Wxpusher 推送参数,需要将pushmethod指定为wxpusher,应用和uid的免费申请参考:https://wxpusher.zjiecode.com/ 45 | appToken = AT_6kBmt*************************** 46 | wxpusheruid = UID_t*************************** 47 | 48 | # Bark 推送参数, 请参考https://github.com/Finb/Bark, 公用默认服务器为https://api.day.app/ 49 | barkServer = https://api.day.app 50 | barkKey = 51 | -------------------------------------------------------------------------------- /compose/init.config: -------------------------------------------------------------------------------- 1 | # setting.config(UTF-8) 2 | 3 | [token] 4 | # 网易云音乐账号(手机号) 5 | account = 6 | 7 | # 密码,明文,请直接输入明文,不需要加密,下方md5Switch请选择false,true会造成二次加密 8 | password = 9 | 10 | # 国家码,用于国外手机号登陆,国内为86 11 | countrycode = 12 | 13 | # 歌单id,请自行选择一个歌曲数量大于300的歌单,歌单id获取方式查看readme 14 | al_id = 123456 15 | 16 | 17 | [setting] 18 | # 接口API,开关的选项只有 True 和 False 19 | # 如需使用本项目还请自行部署API,地址:https://github.com/ZainCheung/netease-cloud-api 20 | api = http://service-musicapi:3000/ 21 | 22 | # 该项不要更改,保持false即可 23 | md5Switch = false 24 | 25 | # 是否开启多账号功能,如果打开将会忽视配置文件里的账号而从account.json中寻找账号信息 26 | # 如果选择使用多账号,请配置好account里的账号和密码,即account和password,而sckey不是必需的,如果为空则不会进行微信推送 27 | # 介于账号安全着想,account.json中的密码必须填写md5加密过的,请不要向他人透露自己的明文密码 28 | peopleSwitch = true 29 | 30 | # 推送方式选择 31 | # 可选参数wxpusher、SCTurbo或留空 32 | # wxpusher: 使用 WxPusher 推送 33 | # SCTurbo: 使用 Server酱Turbo版 推送 34 | # Bark: 使用 Bark 推送 35 | # 留空:使用 Server酱免费版 推送或不推送 36 | pushmethod = 37 | 38 | # Server酱的密匙,不需要推送就留空 39 | # 免费版密匙的免费申请参考:http://sc.ftqq.com/ 40 | # Turbo版的密钥获取:https://sct.ftqq.com/sendkey 41 | # 免费版和Turbo版的密钥长度不一样,请注意检查,不可混用 42 | sckey = SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9******** 43 | 44 | # Wxpusher 推送参数,需要将pushmethod指定为wxpusher,应用和uid的免费申请参考:https://wxpusher.zjiecode.com/ 45 | appToken = AT_6kBmt*************************** 46 | wxpusheruid = UID_t*************************** 47 | 48 | # Bark 推送参数, 请参考https://github.com/Finb/Bark, 公用默认服务器为https://api.day.app/ 49 | barkServer = https://api.day.app 50 | barkKey = 51 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 网易云音乐升级 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/question/README.md: -------------------------------------------------------------------------------- 1 | # 常见问题 {docsify-ignore-all} 2 | 3 | ### 1. 确保自己的账号密码都没有问题,却总是提示检查账号密码怎么回事? 4 | 5 | 答:很有可能是当前的API不可用了,默认API使用的人较多,,而且大多都挤在一个时间段用了,,导致平台反应不过来,本身就是国外站,速度比较慢,大家可以分开点做任务,下午晚上都是可以的,不然这个API就会被挤挂掉了,还是建议大家自己搭建API,这样自己访问速度也会快很多。 6 | 大家部署完API记得在 **init.config**文件中更改 **api**地址为自己部署的地址,比如你的域名是api.test.com或者api.glitch.me等等。 7 | 8 | 9 | 10 | ### 2. 已经换了API,还是报错检查账号密码? 11 | 12 | 答:如果确定API可以用,但依旧提示账号密码有问题,还请检查一下配置文件的账号密码以及**md5Switch**有没有选对,密码的MD5一定要是**32位小写**,已经有人因为没注意这个而出错的了。 13 | 14 | 并且 **init.config**文件中要更改 **api**地址为自己部署的地址。 15 | 16 | 17 | 18 | ### 3. 打卡完成后为什么歌曲累计播放没有涨或者涨幅很小? 19 | 20 | 答:打卡完成后听歌数量并不会立刻更新,建议等待半小时或者更多一段时间,由于官方计数规则限制,只有从未听过的歌曲才计入总数,所以如果你的播放量本来就很高,建议加大打卡的循环次数,教程见其他事项第三条。 21 | 22 | 23 | 24 | ### 4. 自己用服务器搭建的API,首页能打开,但点击检查没反应? 25 | 26 | 答:API一定要用PHP部署,如果是纯静态是没有任何作用的,建议新手或者小白使用前两种部署方式,有能力者使用第三种。 27 | 28 | ### 5. 使用多账号报错怎么办? 29 | 30 | 答:在确保其他配置没有问题的情况下,检查一下`account.json`里面的格式是否正确,账号与账号之间要有逗号,具体格式参考项目里的案例。 31 | 32 | ### 6. 使用这个会影响我的听歌风格吗? 33 | 34 | 答:刷的歌都来自您的每日推荐歌单,不影响。 35 | 36 | ### 7. 使用这个我的账号安全吗? 37 | 38 | 答:从技术上来说,在配置文件中填写的账号密码无论是自行加密还是让程序加密(MD5其实不是加密,只是一种摘要算法,用来防止文件信息等被篡改),最终API接口收到的都是MD5,假设你使用的是网上随便找的API,即使别人改过代码,保存了你的账号信息,想要通过彩虹表暴力破解,也是大费周章还只能搞到简单的密码,至于大神级别的Hack可能毫无压力,但人家大神也不稀罕做这些,所以说安全性基本上没有问题。 39 | 40 | ### 8. 其他报错 41 | 42 | ##### 错误:{"errorCode":1,"errorMessage":"user code exception caught","stackTrace":"module 'index' has no attribute 'main_handler'"} 43 | 44 | 答:这个是通过云函数部署报的错,原因是没有改执行方法,请看云函数部署那一节的图片内容。 45 | 46 | ##### 错误:在您选择的文件夹里面找不到netease-cloud-master/index.py文件 47 | 48 | 答:重新去GitHub下载最新的项目。 49 | 50 | ##### 错误:腾讯云提示当前函数状态不支持绑定触发器怎么办? 51 | 52 | 答:新用户初次使用需要对角色授权,允许服务代替用户完成对授权资源的操作。操作步骤见官网文档。 53 | 54 | 还有其他问题可以提Issue,遇到程序报错可以截图或者复制报错信息。 -------------------------------------------------------------------------------- /docs/document/README.md: -------------------------------------------------------------------------------- 1 | # 接口文档 2 | 3 | ## 调用前须知 4 | 5 | !> 请不要轻易信任使用他人提供的公开服务,如果使用,填写密码时一定要自己加密MD5,以免发生安全问题,泄露自己的账号和密码。 6 | 7 | !> 为使用方便,降低门槛, 文档示例接口直接使用了 GET 请求,本项目同时支持 GET/POST 请按实际需求使用 8 | 9 | !> 本项目仅供学习使用,请尊重版权,请勿利用此项目从事商业行为 10 | 11 | !> API登陆接口只接收MD5加密后的密码,并且不会储存你的个人信息,原密码除了你自己谁也不知道 12 | 13 | !> 使用本项目不会影响你的听歌风格,刷的歌都来自你的每日推荐歌单。 14 | 15 | ## 登录 16 | 17 | 说明 : 登录有两个接口,建议使用`encodeURIComponent`对密码编码或者使用`POST`请求,避免某些特殊字符无法解析,如`#`(`#`在url中会被识别为hash,而不是query) 18 | 19 | **无论是手机登录还是邮箱登陆,密码都必须使用MD5,不可以直接传入明文** 20 | 21 | 明文例如:123456abcd 22 | 23 | MD5例如:efa224f8de55cb668cd01edbccdfc8a9 24 | 25 | ### 1. 手机登录 26 | 27 | **必选参数 :** 28 | 29 | `uin`: 手机号码 30 | 31 | `pwd`: 密码 32 | 33 | **接口地址 :** `/?do=login` 34 | 35 | **可选参数 :** 36 | 37 | `countrycode`: 国家码,用于国外手机号登陆,例如美国传入:`1`,默认国内为86 38 | 39 | `r`: 0至1的随机数,例如`0.20246864764818318` 40 | 41 | **调用例子 :** `/?do=login&uin=xxx&pwd=yyy` 42 | 43 | ### 2. 邮箱登录 44 | 45 | **必选参数 :** 46 | 47 | `uin`: 163 网易邮箱 48 | 49 | `pwd`: 密码 50 | 51 | **接口地址 :** `/?do=email` 52 | 53 | **调用例子 :** `/?do=email&uin=xxx&pwd=yyy` 54 | 55 | 完成登录后 , 会在浏览器保存一个 Cookies 用作登录凭证 , 大部分 API 都需要用到这个 Cookies,请求会自动带上 Cookies 56 | 57 | ## 签到 58 | 59 | 说明:调用接口这个接口可以签到 60 | 61 | **接口地址 :** `/?do=sign` 62 | 63 | ## 打卡听歌 64 | 65 | 说明:由于网易云官方问题,如果打卡听歌只刷了一部分,可以多请求几次,建议每次间隔30秒请求3次左右 66 | 67 | **接口地址 :** `/?do=daka` 68 | 69 | ## 获取用户详情 70 | 71 | 说明 : 登陆后调用此接口 , 传入用户 id, 可以获取用户详情 72 | 73 | **必选参数 :** 74 | 75 | `uid` : 用户 id 76 | 77 | **接口地址 :** `/?do=detail` 78 | 79 | **调用例子 :** `/?do=detail&uid=32953014` 80 | 81 | 注意获取用户信息接口传入的时`uid`,而登陆接口传入的是`uin`,不要搞混淆 82 | 83 | ## 检查接口 84 | 85 | 说明:调用此接口可检查当前项目API是否可用,建议在调用接口前先调用此接口做个判断 86 | 87 | **接口地址 :** `/?do=check` 88 | 89 | ## 刷单曲播放次数 90 | 91 | 说明 : 登陆后调用此接口 , 传入指定歌单id和次数, 可以使该歌单内每首单曲各增加一定的播放次数 92 | 93 | ?> 应用场景常用于定向性训练账号的听歌趋向,可自主纠正系统的个性化推送,让它推送你真正喜欢的内容。这里的次数是指歌单播放次数,比如歌单内有两首歌,次数定为300,则两首歌各增加300次播放次数,如果只想提高某一首歌的次数,那就让这个歌单只留下这一首即可。 94 | 95 | **必选参数 :** 96 | 97 | `id` : 歌单 id 98 | 99 | `time` : 歌单播放次数 100 | 101 | **接口地址 :** `/?do=listen` 102 | 103 | **调用例子 :** `/?do=listen&id=5101628912&time=300` 104 | -------------------------------------------------------------------------------- /docs/sw.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * docsify sw.js 3 | * =========================================================== 4 | * Copyright 2016 @huxpro 5 | * Licensed under Apache 2.0 6 | * Register service worker. 7 | * ========================================================== */ 8 | 9 | const RUNTIME = 'docsify' 10 | const HOSTNAME_WHITELIST = [ 11 | self.location.hostname, 12 | 'fonts.gstatic.com', 13 | 'fonts.googleapis.com', 14 | 'cdn.jsdelivr.net' 15 | ] 16 | 17 | // The Util Function to hack URLs of intercepted requests 18 | const getFixedUrl = (req) => { 19 | var now = Date.now() 20 | var url = new URL(req.url) 21 | 22 | // 1. fixed http URL 23 | // Just keep syncing with location.protocol 24 | // fetch(httpURL) belongs to active mixed content. 25 | // And fetch(httpRequest) is not supported yet. 26 | url.protocol = self.location.protocol 27 | 28 | // 2. add query for caching-busting. 29 | // Github Pages served with Cache-Control: max-age=600 30 | // max-age on mutable content is error-prone, with SW life of bugs can even extend. 31 | // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string. 32 | // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190 33 | if (url.hostname === self.location.hostname) { 34 | url.search += (url.search ? '&' : '?') + 'cache-bust=' + now 35 | } 36 | return url.href 37 | } 38 | 39 | /** 40 | * @Lifecycle Activate 41 | * New one activated when old isnt being used. 42 | * 43 | * waitUntil(): activating ====> activated 44 | */ 45 | self.addEventListener('activate', event => { 46 | event.waitUntil(self.clients.claim()) 47 | }) 48 | 49 | /** 50 | * @Functional Fetch 51 | * All network requests are being intercepted here. 52 | * 53 | * void respondWith(Promise r) 54 | */ 55 | self.addEventListener('fetch', event => { 56 | // Skip some of cross-origin requests, like those for Google Analytics. 57 | if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) { 58 | // Stale-while-revalidate 59 | // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale 60 | // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1 61 | const cached = caches.match(event.request) 62 | const fixedUrl = getFixedUrl(event.request) 63 | const fetched = fetch(fixedUrl, { cache: 'no-store' }) 64 | const fetchedCopy = fetched.then(resp => resp.clone()) 65 | 66 | // Call respondWith() with whatever we get first. 67 | // If the fetch fails (e.g disconnected), wait for the cache. 68 | // If there’s nothing in cache, wait for the fetch. 69 | // If neither yields a response, return offline pages. 70 | event.respondWith( 71 | Promise.race([fetched.catch(_ => cached), cached]) 72 | .then(resp => resp || fetched) 73 | .catch(_ => { /* eat any errors */ }) 74 | ) 75 | 76 | // Update the cache with the version we fetched (only for ok status) 77 | event.waitUntil( 78 | Promise.all([fetchedCopy, caches.open(RUNTIME)]) 79 | .then(([response, cache]) => response.ok && cache.put(event.request, response)) 80 | .catch(_ => { /* eat any errors */ }) 81 | ) 82 | } 83 | }) -------------------------------------------------------------------------------- /docs/config/README.md: -------------------------------------------------------------------------------- 1 | # 配置账号 2 | 3 | !> 为了保护账号信息,所有的账号密匙都打上了*号,使用时请换成自己的账号 4 | 5 | 打开`init.config`文件,进行配置 6 | 7 | ```bash 8 | # setting.config(UTF-8) 9 | ``` 10 | 11 | 第一句注释是为了声明编码格式,请不要删除该行注释 12 | 13 | ------ 14 | 15 | 16 | 17 | ## 账号 18 | 19 | ```bash 20 | [token] 21 | # 网易云音乐账号(手机号/网易邮箱) 22 | account = 150******** 23 | 24 | # 密码,明文/MD5,建议自己去MD5在线加密网站给密码加密,然后填到下面 25 | # 明文例如:123456abcd 26 | # MD5例如:efa224f8de55cb668cd01edbccdfc8a9 27 | password = bfa834f7de58cb650ca01edb******** 28 | 29 | # 国家码,用于国外手机号登陆,国内为86 30 | countrycode = 86 31 | ``` 32 | 33 | `token`区域下存放个人账号信息,`account`存放网易云账号,`password`存放密码,`countrycode`为手机号的国家码 34 | 35 | !> 注意,这里密码填写类型与后面的md5开关相关联,具体见后面介绍 36 | 37 | ------ 38 | 39 | 40 | 41 | ## 设置 42 | 43 | ```bash 44 | [setting] 45 | # 开关的选项只有 True 和 False 46 | # 打卡网站的网址,如果失效请提issue:https://github.com/ZainCheung/netease-cloud-api/issues/new 47 | api = https://netease-cloud-api.glitch.me/ 48 | ``` 49 | 50 | api是指提供接口的服务器地址,这里提供一个Demo,源码也已经全部开源,如有对项目存在疑问欢迎查看源码,项目地址:[ZainCheung/netease-cloud-api](https://github.com/ZainCheung/netease-cloud-api) 51 | 52 | 另外想快速拥有一个一模一样的api服务并且使用自己定义的域名,那么可以按照上面项目的教程自己快速搭建 53 | 54 | ------ 55 | 56 | 57 | 58 | ### MD5 59 | 60 | 61 | ```bash 62 | # 密码是否需要MD5加密,如果是明文密码一定要打开 63 | # true 需要, 则直接将你的密码(明文)填入password,程序会替你进行加密 64 | # false 不需要, 那就自己计算出密码的MD5,然后填入上面的password内 65 | md5Switch = false 66 | ``` 67 | 68 | md5开关,如果自己不会加密md5,那么将这个开关置为true,并且将你的密码(明文)填入password,程序会为你加密。如果已经知道密码的md5,则将这个开关置为false,将md5填入上面的password内 69 | 70 | !> 自己制作MD5时一定要是32位小写!!! 71 | 72 | ------ 73 | 74 | 75 | 76 | ### 任务推送 77 | 78 | ```bash 79 | # 推送方式选择 80 | # 可选参数wxpusher、SCTurbo或留空 81 | # wxpusher: 使用 WxPusher 推送 82 | # SCTurbo: 使用 Server酱Turbo版 推送 83 | # 留空:使用 Server酱免费版 推送或不推送 84 | pushmethod = 85 | 86 | # Server酱的密匙,不需要推送就留空 87 | # 免费版密匙的免费申请参考:http://sc.ftqq.com/ 88 | # Turbo版的密钥获取:https://sct.ftqq.com/sendkey 89 | # 免费版和Turbo版的密钥长度不一样,请注意检查,不可混用 90 | sckey = SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9******** 91 | 92 | # Wxpusher 推送参数,需要将pushmethod指定为wxpusher,应用和uid的免费申请参考:https://wxpusher.zjiecode.com/ 93 | appToken = AT_6kBmt*************************** 94 | wxpusheruid = UID_t*************************** 95 | ``` 96 | 97 | 新版本新增了WxPusher微信推送服务和Server酱的订阅版推送,可通过更改`pushmethod`自行选择推送方式;`sckey`内容为自己申请的Server酱微信推送服务的密钥,分为免费版和订阅版,具体选择看个人需求;`appToken`和`wxpusheruid`都是WxPusher需要的参数,如果推送方式选择了WxPusher则需要配置。 98 | 99 | 附:Server酱,是一个可以向你的微信推送消息的服务,并且消息内容完全自定义,使用之前只需要前往官网,使用GitHub登陆,扫码绑定微信,便可以获得密匙,从此免费使用Server酱。 100 | 101 | ------ 102 | 103 | 104 | 105 | ## 配置多账号 106 | 107 | ```bash 108 | # 是否开启多账号功能,如果打开将会忽视配置文件里的账号而从account.json中寻找账号信息 109 | # 如果选择使用多账号,请配置好account里的账号和密码,即account和password,而sckey不是必需的,如果为空则不会进行微信推送 110 | # 介于账号安全着想,account.json中的密码必须填写md5加密过的,请不要向他人透露自己的明文密码 111 | peopleSwitch = false 112 | ``` 113 | 114 | 这个开关是为那些拥有多账号或者准备带朋友一起使用的朋友准备的,正如注释所说,如果你有多个账号,都想使用这个服务,那么可以打开`peopleSwitch`置为true,那么配置文件里的账号就会被程序忽略,直接读取`account.json`中的账号信息。 115 | 116 | 第一次打开`account.json`,内容会是这样 117 | 118 | ```json 119 | [ 120 | { 121 | "account": "ZainCheung@163.com", 122 | "password": "10ca5e4c316f81c5d9b56702********", 123 | "sckey": "SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9********", 124 | "pushmethod": "", 125 | "appToken": "", 126 | "wxpusheruid": "" 127 | }, 128 | { 129 | "account": "150********", 130 | "password": "bfa834f7de58cb650ca01edb********", 131 | "sckey": "SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9********", 132 | "pushmethod": "", 133 | "appToken": "", 134 | "wxpusheruid": "" 135 | }, 136 | { 137 | "account": "132********", 138 | "password": "f391235b15781c95384cd5bb********", 139 | "sckey": "SCU97783T70c13167b4daa422f4d419a765eb4ebb5ebc9********", 140 | "pushmethod": "", 141 | "appToken": "", 142 | "wxpusheruid": "" 143 | } 144 | ] 145 | ``` 146 | 147 | 可见里面是一个数组文件,成员为账号对象,对象有六个属性,分别是账号、密码、Server酱密匙,推送方式以及WxPusher所需要的两个配置项。 148 | 149 | `pushmethod`留空默认为Server推送;`sckey`留空默认不推送。 150 | 151 | 不同的账号对应不同的推送方法和相应的密匙,在做完这个账号的任务后会给这个密匙绑定的微信发送消息提醒,如果留空则不提醒,留空也请注意语法,记得加双引号,列举一个正确的案例 152 | 153 | ```json 154 | [ 155 | { 156 | "account": "ZainCheung@163.com", 157 | "password": "10ca5e4c316f81c5d9b56702********", 158 | "sckey": "", 159 | "pushmethod": "", 160 | "appToken": "", 161 | "wxpusheruid": "" 162 | }, 163 | ] 164 | ``` 165 | 166 | 可见这里的`sckey`和`pushmethod`都为空,那么完成任务后便不会发送消息提醒,如果不确定是否成功可以查看日志 -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | ''' 3 | @author: ZainCheung 4 | @LastEditors: ZainCheung 5 | @description:网易云音乐全自动每日打卡云函数版 6 | @Date: 2020-06-25 14:28:48 7 | @LastEditTime: 2020-09-01 18:20:00 8 | ''' 9 | from configparser import ConfigParser 10 | from threading import Timer 11 | import requests 12 | import random 13 | import hashlib 14 | import datetime 15 | import time 16 | import json 17 | import logging 18 | import math 19 | 20 | logger = logging.getLogger() 21 | grade = [10,40,70,130,200,400,1000,3000,8000,20000] 22 | api = '' 23 | 24 | class Task(object): 25 | 26 | ''' 27 | 对象的构造函数 28 | ''' 29 | def __init__(self, uin, pwd, pushmethod, sckey, appToken, wxpusheruid, barkServer, barkKey, countrycode): 30 | self.uin = uin 31 | self.pwd = pwd 32 | self.countrycode = countrycode 33 | self.pushmethod = pushmethod 34 | self.sckey = sckey 35 | self.appToken = appToken 36 | self.wxpusheruid = wxpusheruid 37 | self.barkServer = barkServer 38 | if barkServer == "": 39 | self.barkServer = "https://api.day.app" 40 | self.barkKey = barkKey 41 | ''' 42 | 带上用户的cookie去发送数据 43 | url:完整的URL路径 44 | postJson:要以post方式发送的数据 45 | 返回response 46 | ''' 47 | def getResponse(self, url, postJson): 48 | response = requests.post(url, data=postJson, headers={'Content-Type':'application/x-www-form-urlencoded'},cookies=self.cookies) 49 | return response 50 | 51 | ''' 52 | 登录 53 | ''' 54 | def login(self): 55 | data = {"uin":self.uin,"pwd":self.pwd,"countrycode":self.countrycode,"r":random.random()} 56 | if '@' in self.uin: 57 | url = api + '?do=email' 58 | else: 59 | url = api + '?do=login' 60 | response = requests.post(url, data=data, headers={'Content-Type':'application/x-www-form-urlencoded'}) 61 | code = json.loads(response.text)['code'] 62 | self.name = json.loads(response.text)['profile']['nickname'] 63 | self.uid = json.loads(response.text)['account']['id'] 64 | if code==200: 65 | self.error = '' 66 | else: 67 | self.error = '登录失败,请检查账号' 68 | self.cookies = response.cookies.get_dict() 69 | self.log('登录成功') 70 | 71 | ''' 72 | 每日签到 73 | ''' 74 | def sign(self): 75 | url = api + '?do=sign' 76 | response = self.getResponse(url, {"r":random.random()}) 77 | data = json.loads(response.text) 78 | if data['code'] == 200: 79 | self.log('签到成功') 80 | else: 81 | self.log('重复签到') 82 | 83 | ''' 84 | 每日打卡300首歌 85 | ''' 86 | def daka(self): 87 | url = api + '?do=daka' 88 | response = self.getResponse(url, {"r":random.random()}) 89 | self.log(response.text) 90 | 91 | ''' 92 | 查询用户详情 93 | ''' 94 | def detail(self): 95 | url = api + '?do=detail' 96 | data = {"uid":self.uid, "r":random.random()} 97 | response = self.getResponse(url, data) 98 | data = json.loads(response.text) 99 | self.level = data['level'] 100 | self.listenSongs = data['listenSongs'] 101 | self.log('获取用户详情成功') 102 | 103 | ''' 104 | Wxpusher推送 105 | ''' 106 | def wxpusher(self): 107 | if self.appToken == '' or self.wxpusheruid == '': 108 | self.log('未填写WxPusher推送所需参数,请检查') 109 | return 110 | self.diyText() # 构造发送内容 111 | url = 'https://wxpusher.zjiecode.com/api/send/message/' 112 | data = json.dumps({ 113 | "appToken":self.appToken, 114 | "content":self.content, 115 | "summary":self.title, 116 | "contentType":3, 117 | "uids":[self.wxpusheruid] 118 | }) 119 | response = requests.post(url, data = data, headers = {'Content-Type': 'application/json;charset=UTF-8'}) 120 | if (response.json()['data'][0]['status']) == '创建发送任务成功': 121 | self.log('用户:' + self.name + ' WxPusher推送成功') 122 | else: 123 | self.log('用户:' + self.name + ' WxPusher推送失败,请检查appToken和uid是否正确') 124 | 125 | ''' 126 | Bark推送 127 | ''' 128 | def bark(self): 129 | if self.barkServer == '' or self.barkKey == '': 130 | self.log('未填写Bark推送所需参数,请检查') 131 | return 132 | self.diyText() # 构造发送内容 133 | url = self.barkServer+'/push' 134 | data = json.dumps({ 135 | "title": self.title, 136 | "body": self.content, 137 | "device_key": self.barkKey, 138 | "ext_params": {"group": "网易云签到"} 139 | }) 140 | response = requests.post(url, data=data, headers={'Content-Type': 'application/json;charset=UTF-8'}) 141 | if (response.json()['message']) == 'success': 142 | self.log('用户:' + self.name + ' Bark推送成功') 143 | else: 144 | self.log('用户:' + self.name + ' bark推送失败,请检查appToken和uid是否正确') 145 | 146 | ''' 147 | 自定义要推送到微信的内容 148 | title:消息的标题 149 | content:消息的内容,支持MarkDown格式 150 | contentType:消息类型,1为普通文本,2为html,3为markdown 151 | ''' 152 | 153 | ''' 154 | Server推送 155 | ''' 156 | def server(self): 157 | if self.sckey == '': 158 | return 159 | self.diyText() # 构造发送内容 160 | data = { 161 | "text" : self.title, 162 | "desp" : self.content 163 | } 164 | if self.pushmethod.lower() == 'scturbo': #Server酱 Turbo版 165 | url = 'https://sctapi.ftqq.com/' + self.sckey + '.send' 166 | response = requests.post(url, data=data, headers = {'Content-type': 'application/x-www-form-urlencoded'}) 167 | errno = response.json()['data']['errno'] 168 | else: #Server酱 普通版 169 | url = 'https://sct.ftqq.com/' + self.sckey + '.send' 170 | response = requests.post(url, data=data, headers = {'Content-type': 'application/x-www-form-urlencoded'}) 171 | errno = response.json()['errno'] 172 | if errno == 0: 173 | self.log('用户:' + self.name + ' Server酱推送成功') 174 | else: 175 | self.log('用户:' + self.name + ' Server酱推送失败,请检查sckey是否正确') 176 | 177 | ''' 178 | 自定义要推送到微信的内容 179 | title:消息的标题 180 | content:消息的内容,支持MarkDown格式 181 | ''' 182 | 183 | def diyText(self): 184 | # today = datetime.date.today() 185 | # kaoyan_day = datetime.date(2020,12,21) #2021考研党的末日 186 | # date = (kaoyan_day - today).days 187 | for count in grade: 188 | if self.level < 10: 189 | if self.listenSongs < 20000: 190 | if self.listenSongs < count: 191 | self.tip = '还需听歌' + str(count-self.listenSongs) + '首即可升级' 192 | break 193 | else: 194 | self.tip = '你已经听够20000首歌曲,如果登录天数达到800天即可满级' 195 | else: 196 | self.tip = '恭喜你已经满级!' 197 | if self.error == '': 198 | state = ("- 目前已完成签到\n" 199 | "- 今日共打卡" + str(self.dakanum) + "次\n" 200 | "- 今日共播放" + str(self.dakaSongs) + "首歌\n" 201 | "- 还需要打卡" + str(self.day) +"天") 202 | self.title = ("网易云今日打卡" + str(self.dakaSongs) + "首,已播放" + str(self.listenSongs) + "首") 203 | else: 204 | state = self.error 205 | self.title = '网易云听歌任务出现问题!' 206 | self.content = ( 207 | "------\n" 208 | "#### 账户信息\n" 209 | "- 用户名称:" + str(self.name) + "\n" 210 | "- 当前等级:" + str(self.level) + "级\n" 211 | "- 累计播放:" + str(self.listenSongs) + "首\n" 212 | "- 升级提示:" + self.tip + "\n\n" 213 | "------\n" 214 | "#### 任务状态\n" + str(state) + "\n\n" 215 | "------\n" 216 | "#### 打卡日志\n" + self.dakaSongs_list + "\n\n") 217 | 218 | ''' 219 | 打印日志 220 | ''' 221 | def log(self, text): 222 | time_stamp = datetime.datetime.now() 223 | print(time_stamp.strftime('%Y.%m.%d-%H:%M:%S') + ' ' + str(text)) 224 | self.time =time_stamp.strftime('%H:%M:%S') 225 | self.list.append("- [" + self.time + "] " + str(text) + "\n\n") 226 | 227 | ''' 228 | 开始执行 229 | ''' 230 | def start(self): 231 | try: 232 | self.list = [] 233 | self.list.append("- 初始化完成\n\n") 234 | self.login() 235 | self.sign() 236 | self.detail() 237 | counter = self.listenSongs 238 | for i in range(1, 10): 239 | self.daka() 240 | #self.log('用户:' + self.name + ' 第' + str(i) + '次打卡成功,即将休眠10秒') 241 | self.log('第' + str(i) + '次打卡成功,即将休眠10秒') 242 | time.sleep(10) 243 | self.dakanum = i 244 | self.detail() 245 | self.dakaSongs = self.listenSongs - counter 246 | self.log('今日已打卡播放' + str(self.dakaSongs) + '首') 247 | if self.dakaSongs == 300: 248 | break 249 | if self.listenSongs >= 20000: 250 | self.day = 0 251 | else: 252 | self.day = math.ceil((20000 - self.listenSongs)/300) 253 | self.list.append("- 打卡结束,消息推送\n\n") 254 | self.dakaSongs_list = ''.join(self.list) 255 | if self.pushmethod.lower() == 'wxpusher': 256 | self.wxpusher() 257 | elif self.pushmethod.lower() == 'bark': 258 | self.bark() 259 | else: 260 | self.server() 261 | except: 262 | self.log('用户任务执行中断,请检查账号密码是否正确') 263 | else: 264 | self.log('用户:' + self.name + ' 今日任务已完成') 265 | 266 | 267 | ''' 268 | 初始化:读取配置,配置文件为init.config 269 | 返回字典类型的配置对象 270 | ''' 271 | def init(): 272 | global api # 初始化时设置api 273 | config = ConfigParser() 274 | config.read('init.config', encoding='UTF-8-sig') 275 | uin = config['token']['account'] 276 | pwd = config['token']['password'] 277 | countrycode = config['token']['countrycode'] 278 | api = config['setting']['api'] 279 | md5Switch = config.getboolean('setting','md5Switch') 280 | peopleSwitch = config.getboolean('setting','peopleSwitch') 281 | pushmethod = config['setting']['pushmethod'] 282 | sckey = config['setting']['sckey'] 283 | appToken = config['setting']['appToken'] 284 | wxpusheruid = config['setting']['wxpusheruid'] 285 | barkServer = config['setting']['barkServer'] 286 | barkKey = config['setting']['barkKey'] 287 | logger.info('配置文件读取完毕') 288 | conf = { 289 | 'uin': uin, 290 | 'pwd': pwd, 291 | 'countrycode': countrycode, 292 | 'api': api, 293 | 'md5Switch': md5Switch, 294 | 'peopleSwitch':peopleSwitch, 295 | 'pushmethod':pushmethod, 296 | 'sckey':sckey, 297 | 'appToken':appToken, 298 | 'wxpusheruid':wxpusheruid, 299 | 'barkServer':barkServer, 300 | 'barkKey':barkKey 301 | } 302 | return conf 303 | 304 | ''' 305 | MD5加密 306 | str:待加密字符 307 | 返回加密后的字符 308 | ''' 309 | def md5(str): 310 | hl = hashlib.md5() 311 | hl.update(str.encode(encoding='utf-8')) 312 | return hl.hexdigest() 313 | 314 | ''' 315 | 加载Json文件 316 | jsonPath:json文件的名字,例如account.json 317 | ''' 318 | def loadJson(jsonPath): 319 | with open(jsonPath,encoding='utf-8') as f: 320 | account = json.load(f) 321 | return account 322 | 323 | ''' 324 | 检查api 325 | ''' 326 | def check(): 327 | url = api + '?do=check' 328 | respones = requests.get(url) 329 | if respones.status_code == 200: 330 | logger.info('api测试正常') 331 | else: 332 | logger.error('api测试异常') 333 | 334 | ''' 335 | 任务池 336 | ''' 337 | def taskPool(): 338 | 339 | config = init() 340 | check() # 每天对api做一次检查 341 | if config['peopleSwitch'] is True: 342 | logger.info('多人开关已打开,即将执行进行多人任务') 343 | account = loadJson("account.json") 344 | for man in account: 345 | logger.info('账号: ' + man['account'] + ' 开始执行\n========================================') 346 | task = Task(man['account'], man['password'], man['pushmethod'], man['sckey'], man['appToken'], man['wxpusheruid'], man['barkServer'], man['barkKey'], man['countrycode']) 347 | task.start() 348 | time.sleep(10) 349 | logger.info('所有账号已全部完成任务,服务进入休眠中,等待明天重新启动') 350 | else : 351 | logger.info('账号: ' + config['uin'] + ' 开始执行\n========================================') 352 | if config['md5Switch'] is True: 353 | logger.info('MD5开关已打开,即将开始为你加密,密码不会上传至服务器,请知悉') 354 | config['pwd'] = md5(config['pwd']) 355 | task = Task(config['uin'], config['pwd'], config['pushmethod'], config['sckey'], config['appToken'], config['wxpusheruid'], config['barkServer'], config['barkKey'], config['countrycode']) 356 | task.start() 357 | 358 | ''' 359 | 程序的入口 360 | ''' 361 | def main(event,content): 362 | taskPool() 363 | 364 | if __name__ == '__main__': 365 | taskPool() 366 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from configparser import ConfigParser 2 | from threading import Timer 3 | import requests 4 | import random 5 | import hashlib 6 | import datetime 7 | import time 8 | import json 9 | import logging 10 | import math 11 | import os 12 | 13 | ''' 14 | 使用绝对路径时,切换到项目的当前目录。 15 | ''' 16 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 17 | logFile = open("run.log", encoding="utf-8", mode="a") 18 | logging.basicConfig(stream=logFile, format="%(asctime)s %(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO) 19 | grade = [10,40,70,130,200,400,1000,3000,8000,20000] 20 | api = '' 21 | 22 | # 全局变量控制歌单游标 23 | songListOffset = 0 24 | 25 | class Task(object): 26 | 27 | ''' 28 | 对象的构造函数 29 | ''' 30 | 31 | music_num_id = 0 32 | music_list = [] 33 | al_music_list = [] 34 | 35 | def __init__(self, uin, pwd, al_id, pushmethod, sckey, appToken, wxpusheruid, barkServer, barkKey, countrycode): 36 | self.uin = uin 37 | self.pwd = pwd 38 | self.al_id = al_id 39 | self.countrycode = countrycode 40 | self.pushmethod = pushmethod 41 | self.sckey = sckey 42 | self.appToken = appToken 43 | self.wxpusheruid = wxpusheruid 44 | self.barkServer = barkServer 45 | if barkServer == "": 46 | self.barkServer = "https://api.day.app" 47 | self.barkKey = barkKey 48 | ''' 49 | 带上用户的cookie去发送数据 50 | url:完整的URL路径 51 | postJson:要以post方式发送的数据 52 | 返回response 53 | ''' 54 | def getResponse(self, url, postJson): 55 | response = requests.post(url, data=postJson, headers={'Content-Type':'application/x-www-form-urlencoded'},cookies=self.cookies) 56 | return response 57 | 58 | ''' 59 | 登录 60 | ''' 61 | def login(self): 62 | data = {"uin":self.uin,"pwd":self.pwd,"countrycode":self.countrycode,"r":random.random()} 63 | if '@' in self.uin: 64 | url = api + '?do=email' 65 | else: 66 | url = api + 'login/cellphone?phone='+ str(self.uin) + '&password=' + str(self.pwd) 67 | response = requests.post(url, data=data, headers={'Content-Type':'application/x-www-form-urlencoded'}) 68 | code = json.loads(response.text)['code'] 69 | self.name = json.loads(response.text)['profile']['nickname'] 70 | self.uid = json.loads(response.text)['account']['id'] 71 | if code==200: 72 | self.error = '' 73 | else: 74 | self.error = '登录失败,请检查账号' 75 | self.cookies = response.cookies.get_dict() 76 | self.log('登录成功') 77 | logging.info("登录成功") 78 | 79 | ''' 80 | 每日签到 81 | ''' 82 | def sign(self): 83 | url = api + 'daily_signin' 84 | response = self.getResponse(url, {"r":random.random()}) 85 | data = json.loads(response.text) 86 | if data['code'] == 200: 87 | self.log('签到成功') 88 | logging.info('签到成功') 89 | else: 90 | self.log('重复签到') 91 | logging.info('重复签到') 92 | 93 | 94 | ''' 95 | 获取歌单里全部歌曲id 96 | ''' 97 | def allmus(self): 98 | global songListOffset 99 | url = url = api + 'playlist/track/all?id=' + str(self.al_id) + '&limit=300&offset=' + str(songListOffset) 100 | response = self.getResponse(url, {"r":random.random()}) 101 | json_dict = json.loads(response.text) 102 | for i in range(0, 300): 103 | self.music_list.append(json_dict['songs'][i]['id']) 104 | self.al_music_list.append(json_dict['songs'][i]['al']['id']) 105 | 106 | logging.info('歌单获取成功,本次将从第 ' + str(songListOffset + 1) + '首歌曲开始打卡!') 107 | logging.info('歌曲id为:' + str(self.music_list[0])) 108 | songListOffset += 300 109 | 110 | ''' 111 | 每日打卡300首歌 112 | ''' 113 | def daka(self, num): 114 | url = api + 'scrobble?id='+str(self.music_list[num])+'&sourceid='+str(self.al_music_list[num])+'&time=61' 115 | response = self.getResponse(url, {"r":random.random()}) 116 | self.music_num_id += 1 117 | 118 | ''' 119 | 查询用户详情 120 | ''' 121 | def detail(self): 122 | url = api + 'user/detail' 123 | data = {"uid":self.uid, "r":random.random()} 124 | response = self.getResponse(url, data) 125 | data = json.loads(response.text) 126 | self.level = data['level'] 127 | self.listenSongs = data['listenSongs'] 128 | self.log('获取用户详情成功') 129 | logging.info('获取用户详情成功') 130 | 131 | 132 | ''' 133 | Wxpusher推送 134 | ''' 135 | def wxpusher(self): 136 | if (self.appToken == '' or self.wxpusheruid == ''): 137 | self.log('未填写WxPusher推送所需参数,请检查') 138 | logging.info('未填写WxPusher推送所需参数,请检查') 139 | return 140 | self.diyText() # 构造发送内容 141 | url = 'https://wxpusher.zjiecode.com/api/send/message/' 142 | data = json.dumps({ 143 | "appToken":self.appToken, 144 | "content":self.content, 145 | "summary":self.title, 146 | "contentType":3, 147 | "uids":[self.wxpusheruid] 148 | }) 149 | response = requests.post(url, data = data, headers = {'Content-Type': 'application/json;charset=UTF-8'}) 150 | if (response.json()['data'][0]['status']) == '创建发送任务成功': 151 | self.log('用户:' + self.name + ' WxPusher推送成功') 152 | logging.info('用户:' + self.name + ' WxPusher推送成功') 153 | else: 154 | self.log('用户:' + self.name + ' WxPusher推送失败,请检查appToken和uid是否正确') 155 | logging.info('用户:' + self.name + ' WxPusher推送失败,请检查appToken和uid是否正确') 156 | 157 | ''' 158 | Bark推送 159 | ''' 160 | def bark(self): 161 | if self.barkServer == '' or self.barkKey == '': 162 | self.log('未填写Bark推送所需参数,请检查') 163 | return 164 | self.diyText() # 构造发送内容 165 | url = self.barkServer+'/push' 166 | data = json.dumps({ 167 | "title": self.title, 168 | "body": self.content, 169 | "device_key": self.barkKey, 170 | "ext_params": {"group": "网易云签到"} 171 | }) 172 | response = requests.post(url, data=data, headers={'Content-Type': 'application/json;charset=UTF-8'}) 173 | if (response.json()['message']) == 'success': 174 | self.log('用户:' + self.name + ' Bark推送成功') 175 | else: 176 | self.log('用户:' + self.name + ' bark推送失败,请检查appToken和uid是否正确') 177 | 178 | ''' 179 | 自定义要推送到微信的内容 180 | title:消息的标题 181 | content:消息的内容,支持MarkDown格式 182 | contentType:消息类型,1为普通文本,2为html,3为markdown 183 | ''' 184 | 185 | ''' 186 | Server推送 187 | ''' 188 | def server(self): 189 | if self.sckey == '': 190 | return 191 | self.diyText() # 构造发送内容 192 | data = { 193 | "text":self.title, 194 | "desp":self.content 195 | } 196 | if (self.pushmethod.lower() == 'scturbo'): #Server酱 Turbo版 197 | url = 'https://sctapi.ftqq.com/' + self.sckey + '.send' 198 | response = requests.post(url, data=data, headers = {'Content-type': 'application/x-www-form-urlencoded'}) 199 | errno = response.json()['data']['errno'] 200 | else: #Server酱 普通版 201 | url = 'http://sc.ftqq.com/' + self.sckey + '.send' 202 | response = requests.post(url, data=data, headers = {'Content-type': 'application/x-www-form-urlencoded'}) 203 | errno = response.json()['errno'] 204 | if errno == 0: 205 | self.log('用户:' + self.name + ' Server酱推送成功') 206 | logging.info('用户:' + self.name + ' Server酱推送成功') 207 | else: 208 | self.log('用户:' + self.name + ' Server酱推送失败,请检查sckey是否正确') 209 | logging.info('用户:' + self.name + ' Server酱推送失败,请检查sckey是否正确') 210 | 211 | ''' 212 | 自定义要推送到微信的内容 213 | title:消息的标题 214 | content:消息的内容,支持MarkDown格式 215 | ''' 216 | 217 | def diyText(self): 218 | # today = datetime.date.today() 219 | # kaoyan_day = datetime.date(2020,12,21) #2021考研党的末日 220 | # date = (kaoyan_day - today).days 221 | for count in grade: 222 | if self.level < 10: 223 | if self.listenSongs < 20000: 224 | if self.listenSongs < count: 225 | self.tip = '还需听歌' + str(count-self.listenSongs) + '首即可升级' 226 | break 227 | else: 228 | self.tip = '你已经听够20000首歌曲,如果登录天数达到800天即可满级' 229 | else: 230 | self.tip = '恭喜你已经满级!' 231 | if self.error == '': 232 | state = ("- 目前已完成签到\n" 233 | "- 今日共打卡" + str(self.dakanum) + "次\n" 234 | "- 今日共播放" + str(self.dakaSongs) + "首歌\n" 235 | "- 还需要打卡" + str(self.day) +"天") 236 | self.title = ("网易云今日打卡" + str(self.dakaSongs) + "首,已播放" + str(self.listenSongs) + "首") 237 | else: 238 | state = self.error 239 | self.title = '网易云听歌任务出现问题!' 240 | self.content = ( 241 | "------\n" 242 | "#### 账户信息\n" 243 | "- 用户名称:" + str(self.name) + "\n" 244 | "- 当前等级:" + str(self.level) + "级\n" 245 | "- 累计播放:" + str(self.listenSongs) + "首\n" 246 | "- 升级提示:" + self.tip + "\n\n" 247 | "------\n" 248 | "#### 任务状态\n" + str(state) + "\n\n" 249 | "------\n" 250 | "#### 注意事项\n- 网易云音乐等级数据每天下午2点更新 \n\n" 251 | "------\n" 252 | "#### 打卡日志\n" + self.dakaSongs_list + "\n\n") 253 | 254 | ''' 255 | 打印日志 256 | ''' 257 | def log(self, text): 258 | time_stamp = datetime.datetime.now() 259 | print(time_stamp.strftime('%Y.%m.%d-%H:%M:%S') + ' ' + str(text)) 260 | self.time =time_stamp.strftime('%H:%M:%S') 261 | self.list.append("- [" + self.time + "] " + str(text) + "\n\n") 262 | 263 | ''' 264 | 开始执行 265 | ''' 266 | def start(self): 267 | retry_count = 0 268 | while retry_count <= 3: 269 | try: 270 | self.list = [] 271 | self.list.append("- 初始化完成\n\n") 272 | try: 273 | self.login() 274 | except: 275 | logging.error('\n\n', '登陆失败', '\n\n') 276 | return 277 | try: 278 | self.sign() 279 | except: 280 | logging.error('\n\n', '签到失败', '\n\n') 281 | return 282 | try: 283 | self.detail() 284 | except: 285 | logging.error('\n\n', '获取详情失败', '\n\n') 286 | return 287 | try: 288 | self.allmus() 289 | except: 290 | logging.error('\n\n', '所选歌单数量小于300', '\n\n') 291 | return 292 | counter = self.listenSongs 293 | self.list.append("- 开始打卡\n\n") 294 | for i in range(3, 300): 295 | self.daka(i) 296 | # self.log('用户:' + self.name + ' 第' + str(i) + '次打卡成功,即将休眠30秒') 297 | self.log('第' + str(i) + '次打卡成功') 298 | sleep_time = 60 + random.randint(5, 30) 299 | logging.info('用户:' + self.name + ' 第' + str(i) + '次打卡成功,即将休眠' + str(sleep_time) + '秒') 300 | time.sleep(sleep_time) 301 | self.dakanum =i 302 | self.detail() 303 | self.dakaSongs = self.listenSongs - counter 304 | self.log('今日已打卡' + str(self.dakaSongs) + '首') 305 | if self.dakaSongs == 300: 306 | break 307 | 308 | if self.listenSongs >= 20000: 309 | self.day = 0 310 | else: 311 | self.day = math.ceil((20000 - self.listenSongs)/300) 312 | 313 | self.list.append("- 打卡结束\n\n") 314 | self.list.append("- 消息推送\n\n") 315 | self.dakaSongs_list = ''.join(self.list) 316 | if self.pushmethod.lower() == 'wxpusher': 317 | self.wxpusher() 318 | elif self.pushmethod.lower() == 'bark': 319 | self.bark() 320 | else: 321 | self.server() 322 | except: 323 | self.log('用户任务执行中断,请检查账号密码是否正确') 324 | logging.error('用户任务执行中断,请检查账号密码是否正确========================================') 325 | retry_count += 1 326 | logging.info('60秒后开始重试,最大尝试3次') 327 | time.sleep(60) 328 | logging.info('当前是第:' + retry_counte + '次数重试') 329 | else: 330 | self.log('用户:' + self.name + ' 今日任务已完成') 331 | logging.info('用户:' + self.name + ' 今日任务已完成========================================') 332 | retry_count = 3 333 | 334 | 335 | ''' 336 | 初始化:读取配置,配置文件为init.config 337 | 返回字典类型的配置对象 338 | ''' 339 | def init(): 340 | global api # 初始化时设置api 341 | config = ConfigParser() 342 | config.read('init.config', encoding='UTF-8-sig') 343 | uin = config['token']['account'] 344 | pwd = config['token']['password'] 345 | al_id = config['token']['al_id'] 346 | countrycode = config['token']['countrycode'] 347 | api = config['setting']['api'] 348 | md5Switch = config.getboolean('setting','md5Switch') 349 | peopleSwitch = config.getboolean('setting','peopleSwitch') 350 | pushmethod = config['setting']['pushmethod'] 351 | sckey = config['setting']['sckey'] 352 | appToken = config['setting']['appToken'] 353 | wxpusheruid = config['setting']['wxpusheruid'] 354 | barkServer = config['setting']['barkServer'] 355 | barkKey = config['setting']['barkKey'] 356 | logging.info('配置文件读取完毕') 357 | conf = { 358 | 'uin': uin, 359 | 'pwd': pwd, 360 | 'al_id': al_id, 361 | 'countrycode': countrycode, 362 | 'api': api, 363 | 'md5Switch': md5Switch, 364 | 'peopleSwitch':peopleSwitch, 365 | 'pushmethod':pushmethod, 366 | 'sckey':sckey, 367 | 'appToken':appToken, 368 | 'wxpusheruid':wxpusheruid, 369 | 'barkServer':barkServer, 370 | 'barkKey':barkKey 371 | } 372 | return conf 373 | 374 | ''' 375 | MD5加密 376 | str:待加密字符 377 | 返回加密后的字符 378 | ''' 379 | def md5(str): 380 | hl = hashlib.md5() 381 | hl.update(str.encode(encoding='utf-8')) 382 | return hl.hexdigest() 383 | 384 | ''' 385 | 加载Json文件 386 | jsonPath:json文件的名字,例如account.json 387 | ''' 388 | def loadJson(jsonPath): 389 | with open(jsonPath,encoding='utf-8') as f: 390 | account = json.load(f) 391 | return account 392 | 393 | ''' 394 | 检查api 395 | ''' 396 | def check(): 397 | url = api + '?do=check' 398 | respones = requests.get(url) 399 | if respones.status_code == 200: 400 | logging.info('api测试正常') 401 | else: 402 | logging.error('api测试异常') 403 | 404 | ''' 405 | 任务池 406 | ''' 407 | def taskPool(): 408 | 409 | config = init() 410 | check() # 每天对api做一次检查 411 | if config['peopleSwitch'] is True: 412 | logging.info('多人开关已打开,即将执行进行多人任务') 413 | account = loadJson("account.json") 414 | for man in account: 415 | logging.info('账号: ' + man['account'] + ' 开始执行========================================') 416 | task = Task(man['account'], man['password'], man['al_id'], man['pushmethod'], man['sckey'], man['appToken'], man['wxpusheruid'], man['barkServer'], man['barkKey'], man['countrycode']) 417 | task.start() 418 | time.sleep(10) 419 | logging.info('所有账号已全部完成任务,服务进入休眠中,等待明天重新启动') 420 | else : 421 | logging.info('账号: ' + config['uin'] + ' 开始执行========================================') 422 | if config['md5Switch'] is True: 423 | logging.info('MD5开关已打开,即将开始为你加密,密码不会上传至服务器,请知悉') 424 | config['pwd'] = md5(config['pwd']) 425 | task = Task(config['uin'], config['pwd'], config['al_id'], config['pushmethod'], config['sckey'], config['appToken'], config['wxpusheruid'], config['barkServer'], config['barkKey'], config['countrycode']) 426 | task.start() 427 | 428 | ''' 429 | 程序的入口 430 | ''' 431 | if __name__ == '__main__': 432 | while True: 433 | logging.info('10秒后程序启动') 434 | time.sleep(10) 435 | Timer(0, taskPool, ()).start() 436 | time.sleep(60*60*24) # 间隔一天 437 | --------------------------------------------------------------------------------