index.py 9.4 KB
Newer Older
Z
Zain 已提交
1 2 3
#coding:utf-8
'''
@author: ZainCheung
ZainCheung's avatar
ZainCheung 已提交
4
@LastEditors: ZainCheung
Z
Zain 已提交
5 6
@description:网易云音乐全自动每日打卡云函数版
@Date: 2020-06-25 14:28:48
ZainCheung's avatar
ZainCheung 已提交
7
@LastEditTime: 2020-09-01 18:20:00
Z
Zain 已提交
8 9 10 11 12 13 14 15 16 17
'''
from configparser import ConfigParser
from threading import Timer
import requests 
import random
import hashlib
import datetime
import time
import json
import logging
Daphel's avatar
Daphel 已提交
18
import math
Z
Zain 已提交
19 20 21 22 23 24 25 26 27 28

logger = logging.getLogger()
grade = [10,40,70,130,200,400,1000,3000,8000,20000]
api = ''

class Task(object):
    
    '''
    对象的构造函数
    '''
ZainCheung's avatar
ZainCheung 已提交
29
    def __init__(self, uin, pwd, sckey, countrycode=86):
Z
Zain 已提交
30 31
        self.uin = uin
        self.pwd = pwd
ZainCheung's avatar
ZainCheung 已提交
32
        self.countrycode = countrycode
Z
Zain 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45
        self.sckey = sckey

    '''
    带上用户的cookie去发送数据
    url:完整的URL路径
    postJson:要以post方式发送的数据
    返回response
    '''
    def getResponse(self, url, postJson):
        response = requests.post(url, data=postJson, headers={'Content-Type':'application/x-www-form-urlencoded'},cookies=self.cookies)
        return response

    '''
Daphel's avatar
Daphel 已提交
46
    登录
Z
Zain 已提交
47 48
    '''
    def login(self):
ZainCheung's avatar
ZainCheung 已提交
49
        data = {"uin":self.uin,"pwd":self.pwd,"countrycode":self.countrycode,"r":random.random()}
Z
Zain 已提交
50 51 52 53 54 55 56 57 58 59 60
        if '@' in self.uin:
            url = api + '?do=email'
        else:
            url = api + '?do=login'
        response = requests.post(url, data=data, headers={'Content-Type':'application/x-www-form-urlencoded'})
        code = json.loads(response.text)['code']
        self.name = json.loads(response.text)['profile']['nickname']
        self.uid = json.loads(response.text)['account']['id']
        if code==200:
            self.error = ''
        else:
Daphel's avatar
Daphel 已提交
61
            self.error = '登录失败,请检查账号'
Z
Zain 已提交
62
        self.cookies = response.cookies.get_dict()
Daphel's avatar
Daphel 已提交
63
        self.log('登录成功')
Z
Zain 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

    '''
    每日签到
    '''
    def sign(self):
        url = api + '?do=sign'
        response = self.getResponse(url, {"r":random.random()})
        data = json.loads(response.text)
        if data['code'] == 200:
            self.log('签到成功')
        else:
            self.log('重复签到')

    '''
    每日打卡300首歌
    '''
    def daka(self):
        url = api + '?do=daka'
        response = self.getResponse(url, {"r":random.random()})
        self.log(response.text)

    '''
    查询用户详情
    '''
    def detail(self):
        url = api + '?do=detail'
        data = {"uid":self.uid, "r":random.random()}
        response = self.getResponse(url, data)
        data = json.loads(response.text)
        self.level = data['level']
        self.listenSongs = data['listenSongs']
        self.log('获取用户详情成功')

    '''
    Server推送
    '''
    def server(self):
        if self.sckey == '':
            return
        url = 'https://sc.ftqq.com/' + self.sckey + '.send'
        self.diyText() # 构造发送内容
        response = requests.get(url,params={"text":self.title, "desp":self.content})
        data = json.loads(response.text)
        if data['errno'] == 0:
            self.log('用户:' + self.name + '  Server酱推送成功')
        else:
            self.log('用户:' + self.name + '  Server酱推送失败,请检查sckey是否正确')

    '''
    自定义要推送到微信的内容
    title:消息的标题
    content:消息的内容,支持MarkDown格式
    '''
    def diyText(self):
ZainCheung's avatar
ZainCheung 已提交
118 119 120
        # today = datetime.date.today()
        # kaoyan_day = datetime.date(2020,12,21) #2021考研党的末日
        # date = (kaoyan_day - today).days
Z
Zain 已提交
121 122 123 124 125 126 127 128
        one = requests.get('https://api.qinor.cn/soup/').text # 每日一句的api
        for count in grade:
            if self.level < 10:
                if self.listenSongs < 20000:
                    if self.listenSongs < count:
                        self.tip = '还需听歌' + str(count-self.listenSongs) + '首即可升级'
                        break
                else:
Daphel's avatar
Daphel 已提交
129
                    self.tip = '你已经听够20000首歌曲,如果登录天数达到800天即可满级'
Z
Zain 已提交
130 131 132
            else:
                self.tip = '恭喜你已经满级!'
        if self.error == '':
Daphel's avatar
Daphel 已提交
133 134 135 136 137
            state = ("- 目前已完成签到\n"
                     "- 今日共打卡" + str(self.dakanum) + "次\n"
                     "- 今日共播放" + str(self.dakaSongs) + "首歌\n"
                     "- 还需要打卡" + str(self.day) +"天")
            self.title = ("网易云今日打卡" + str(self.dakaSongs) + "首,已播放" + str(self.listenSongs) + "首")
Z
Zain 已提交
138 139 140
        else:
            state = self.error
            self.title = '网易云听歌任务出现问题!'
Daphel's avatar
Daphel 已提交
141
        self.content = (
Z
Zain 已提交
142
            "------\n"
Daphel's avatar
Daphel 已提交
143 144 145 146 147
            "#### 账户信息\n"
            "- 用户名称:" + str(self.name) + "\n"
            "- 当前等级:" + str(self.level) + "级\n"
            "- 累计播放:" + str(self.listenSongs) + "首\n"
            "- 升级提示:" + self.tip + "\n\n"
Z
Zain 已提交
148
            "------\n"
Daphel's avatar
Daphel 已提交
149 150 151 152 153
            "#### 任务状态\n" + str(state) + "\n\n"
            "------\n"
            "#### 打卡日志\n" + self.dakaSongs_list + "\n\n"
            "------\n"
            "#### 今日一句\n- " + one + "\n\n")
Z
Zain 已提交
154 155 156 157 158 159 160

    '''
    打印日志
    '''
    def log(self, text):
        time_stamp = datetime.datetime.now()
        print(time_stamp.strftime('%Y.%m.%d-%H:%M:%S') + '   ' + str(text))
Daphel's avatar
Daphel 已提交
161 162
        self.time =time_stamp.strftime('%H:%M:%S')
        self.list.append("- [" + self.time + "]  " + str(text) + "\n\n")
Z
Zain 已提交
163 164 165 166 167 168

    '''
    开始执行
    '''
    def start(self):
        try:
Daphel's avatar
Daphel 已提交
169 170
            self.list = []
            self.list.append("- 初始化完成\n\n")
Z
Zain 已提交
171 172 173
            self.login()
            self.sign()
            self.detail()
Daphel's avatar
Daphel 已提交
174 175
            counter  = self.listenSongs
            for i in range(1,10):
Z
Zain 已提交
176
                self.daka()
Daphel's avatar
Daphel 已提交
177 178
                #self.log('用户:' + self.name + '  第' + str(i) + '次打卡成功,即将休眠10秒')
                self.log('第' + str(i) + '次打卡成功,即将休眠10秒')
Z
Zain 已提交
179
                time.sleep(10)
Daphel's avatar
Daphel 已提交
180 181 182 183 184 185 186 187 188 189 190 191
                self.dakanum = i
                self.detail()
                self.dakaSongs = self.listenSongs - counter
                self.log('今日已打卡播放' + str(self.dakaSongs) + '首')
                if self.dakaSongs == 300:
                    break
            if self.listenSongs >= 20000:
                self.day = 0
            else:
                self.day = math.ceil((20000 - self.listenSongs)/300)
            self.list.append("- 打卡结束,消息推送\n\n")
            self.dakaSongs_list = ''.join(self.list)
Z
Zain 已提交
192 193 194 195 196
            self.server()
        except:
            self.log('用户任务执行中断,请检查账号密码是否正确')
        else:
            self.log('用户:' + self.name + '  今日任务已完成')
197
           
Z
Zain 已提交
198 199 200 201 202 203 204 205
        
'''
初始化:读取配置,配置文件为init.config
返回字典类型的配置对象
'''
def init():
    global api # 初始化时设置api
    config = ConfigParser()
Z
Zain 已提交
206
    config.read('init.config', encoding='UTF-8-sig')
Z
Zain 已提交
207 208
    uin = config['token']['account']
    pwd = config['token']['password']
ZainCheung's avatar
ZainCheung 已提交
209
    countrycode = config['token']['countrycode']
Z
Zain 已提交
210 211 212 213 214 215 216 217
    api = config['setting']['api']
    md5Switch = config.getboolean('setting','md5Switch')
    peopleSwitch = config.getboolean('setting','peopleSwitch')
    sckey = config['setting']['sckey']
    logger.info('配置文件读取完毕')
    conf = {
            'uin': uin,
            'pwd': pwd,
ZainCheung's avatar
ZainCheung 已提交
218
            'countrycode': countrycode,
Z
Zain 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
            'api': api,
            'md5Switch': md5Switch, 
            'peopleSwitch':peopleSwitch,
            'sckey':sckey
        }
    return conf

'''
MD5加密
str:待加密字符
返回加密后的字符
'''
def md5(str):
    hl = hashlib.md5()
    hl.update(str.encode(encoding='utf-8'))
    return hl.hexdigest()

'''
加载Json文件
jsonPath:json文件的名字,例如account.json
'''
def loadJson(jsonPath):
    with open(jsonPath,encoding='utf-8') as f:
        account = json.load(f)
    return account

'''
检查api
'''
def check():
    url = api + '?do=check'
    respones = requests.get(url)
    if respones.status_code == 200:
        logger.info('api测试正常')
    else:
        logger.error('api测试异常')

'''
任务池
'''
def taskPool():
    
    config = init()
    check() # 每天对api做一次检查
    if config['peopleSwitch'] is True:
        logger.info('多人开关已打开,即将执行进行多人任务')
        account = loadJson("account.json")
        for man in account:
267
            logger.info('账号: ' + man['account'] + '  开始执行\n========================================')
Z
Zain 已提交
268 269 270 271 272
            task = Task(man['account'], man['password'], man['sckey'])
            task.start()
            time.sleep(10)
        logger.info('所有账号已全部完成任务,服务进入休眠中,等待明天重新启动')
    else :
273
        logger.info('账号: ' + config['uin'] + '  开始执行\n========================================')
Z
Zain 已提交
274 275 276
        if config['md5Switch'] is True:
            logger.info('MD5开关已打开,即将开始为你加密,密码不会上传至服务器,请知悉')
            config['pwd'] = md5(config['pwd'])
ZainCheung's avatar
ZainCheung 已提交
277
        task = Task(config['uin'], config['pwd'], config['sckey'], config['countrycode'])
Z
Zain 已提交
278 279 280 281 282 283 284
        task.start()

'''
程序的入口
'''
def main(event,content):
    taskPool()