Acfun自动老司机:自动按正则回复私信

有人提议,我就写个。
老规矩,GPLv2,自己测试,风险自担。
 
https://gist.github.com/cnbeining/b77a4f5762a78fb3878c
 

#!/usr/bin/env python
#coding:utf-8
# Author: Beining  --<i@cnbeining.com>
# Purpose: Auto reply Acfun's msg
# Created: 01/05/2016
# License: GPLv2
import sys
import unittest
import requests
import json
import urllib.parse
import time
cookiepath = ''
VER = '0.01'
global cookiepath
global HEADER
global UA
import re
global regex_expression_list
regex_expression_list = [
        ('ACICFG', 'Hi!')
    ]
#----------------------------------------------------------------------
def read_cookie(cookiepath):
    """str->list
    Original target: set the cookie
    Target now: Set the global header"""
    #print(cookiepath)
    try:
        cookies_file = open(cookiepath, 'r')
        cookies = cookies_file.readlines()
        cookies_file.close()
        # print(cookies)
        return cookies
    except Exception:
        print('Cannot read cookie, may affect some videos...')
        return ['']
#----------------------------------------------------------------------
def get_unread_list():
    """"""
    req = requests.get('http://www.acfun.tv/api/mail.aspx?name=getGroups&page=1', headers = HEADER)
    content = json.loads(req.content)
    return [str(i) for i in b['unReadList']]
#----------------------------------------------------------------------
def get_last_msg_by_p2p(p2p):
    """"""
    req = requests.get('http://www.acfun.tv/api/mail.aspx?name=getMails&page=1&p2p={p2p}'.format(p2p = p2p), headers = HEADER)
    content = json.loads(req.content)
    return json.loads(content['mailList'][0])
#----------------------------------------------------------------------
def get_regex_object_list(regex_list):
    """"""
    list_this = []
    for i in regex_list:
        list_this.append(((eval('re.compile(r"{regex}")'.format(regex = i[0]))), i[1]))
    return list_this
#----------------------------------------------------------------------
def get_reply_by_text(text):
    """"""
    for i in regex_object_list:
        if i[0].match(mail):
            return i[1]
#----------------------------------------------------------------------
def send_reply(userId, content):
    """"""
    content = urllib.parse.quote(content)
    data = 'userId={userId}&content={content}'.format(userId = userId, content = content)
    requests.post('http://www.acfun.tv/api/mail.aspx?name=newMail', headers=HEADER, data=data)
#----------------------------------------------------------------------
def main():
    """"""
    unReadList = get_unread_list()
    for p2p in unReadList:
        mail = get_last_msg_by_p2p(p2p)
        reply = get_reply_by_text(mail['text'])
        fromuId = mail['fromuId']
        fromusername = mail['fromusername']
        send_reply(fromuId, reply)
        print('Received: {mail} from {fromusername}, Sent: {reply}')
#----------------------------------------------------------------------
def usage():
    """"""
    pass
if __name__=='__main__':
    argv_list = []
    argv_list = sys.argv[1:]
    cookiepath,wait_time = '', 5
    try:
        opts, args = getopt.getopt(argv_list, "hc:t:",
                                   ['help', "cookie=", 'time='])
    except getopt.GetoptError:
        usage()
        exit()
    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            exit()
        if o in ('-c', '--cookie'):
            cookiepath = a
        if o in ('-t', '--time'):
            wait_time = a
    if cookiepath == '':
        cookiepath = './accookies'
    if not os.path.exists(cookiepath):
        print('Unable to open the cookie\'s file!')
        print('Please put your cookie in the file \"bilicookies\" or set a path yourself')
        exit()
    cookies = read_cookie(cookiepath)[0]
    UA = 'Acfun Auto Msg/{VER} (cnbeining@gmail.com) (Python-urllib/{python_ver_str}, like libcurl/1.0 NSS-Mozilla/2.0)'.format(VER = VER, python_ver_str = python_ver_str)
    HEADER = {'User-Agent': UA, 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Cookie': cookies[0]}
    regex_object_list = get_regex_object_list(regex_expression_list)
    global regex_object_list
    while 1:
        main()
        time.sleep(wait_time)

 

又一个开源软件授权协议:GFUL (Go Fuck Yourself public License)


只想让人看源码 剩下的什么都不想要?
嫌偷代码狗太多?没人care GPL?
请选用GFUL。
https://www.cnbeining.com/gful-go-fuck-yourself-license-version-1/

Go Fuck Yourself Public License
Version 1.0, November 2015
Copyright (C) 2015 Beining <i@cnbeining.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document.
Go Fuck Yourself Public License
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You cannot do anything by/to/on/in/with/about/under/through this piece of code. Go fuck yourself.

备份:Bilibili 历史弹幕下载

      No Comments on 备份:Bilibili 历史弹幕下载

原作者的gists死了,备份一下以免灭失。
https://kirito.me/python/download-bilibili-historical-danmu.html

#!/usr/bin/env python
# -*- coding=utf-8 -*-
# 哔哩哔哩历史弹幕 (XML) 下载器
# 使用:downdanmu.py av314
 
import StringIO
import datetime
import gzip
import json
import os
import re
import urllib2
import zlib
 
# 接受参数 av****** 并创建 xml 保存目录
av_number = sys.argv[1]
xml_folder = r'./%s' % av_number
if os.path.exists(xml_folder):
    pass
else:
    os.makedirs(xml_folder)
 
# 处理 bilibili 视频页面
video_page_url = 'http://www.bilibili.tv/video/%s' % av_number
video_page_request = urllib2.Request(video_page_url)
video_page_gz = urllib2.urlopen(video_page_request).read()
# gzip 解压
# 方法来自 [url]http://stackoverflow.com/a/3947241[/url]
video_page_buffer = StringIO.StringIO(video_page_gz)
video_page_html = gzip.GzipFile(fileobj = video_page_buffer).read()
 
# 获取视频 cid
cid_number = re.findall(r'cid=(\d+)', video_page_html)[0]
 
# 获取视频所有历史弹幕
comments_page_url = 'http://comment.bilibili.tv/rolldate,%s' % cid_number
comments_page_request = urllib2.Request(comments_page_url)
comments_page_zip = urllib2.urlopen(comments_page_request).read()
# deflate 解压
# 方法来自 [url]http://stackoverflow.com/a/9583564[/url]
comments_page_json = zlib.decompressobj(-zlib.MAX_WBITS).decompress(comments_page_zip)
 
# 解析历史弹幕信息
comments_python_object = json.loads(comments_page_json)
for i in range(0, len(comments_python_object)):
    comment_timestamp = comments_python_object[i]['timestamp']
    comment_date = datetime.datetime.fromtimestamp(int(comment_timestamp)).strftime('%Y%m%d')
    comment_then_url = 'http://comment.bilibili.tv/dmroll,%s,%s' % (comment_timestamp, cid_number)
    comment_then_request = urllib2.Request(comment_then_url)
    comment_then_zip = urllib2.urlopen(comment_then_request).read()
    comment_then_xml = zlib.decompressobj(-zlib.MAX_WBITS).decompress(comment_then_zip)
    comment_file = open('%s/%s.xml' % (xml_folder, comment_date), 'wb')
    comment_file.write(comment_then_xml)
    comment_file.close()
else:
    pass

 

重新封装一下Bilibili弹幕组件的API

      2 Comments on 重新封装一下Bilibili弹幕组件的API

主要为了算PMF。
不授权任何转载。

import xml.etree.ElementTree as ET
import requests
########################################################################
class BilibiliDanmaku:
    """"""
    cid = 0
    danmaku_list = []
    danmaku_url = 'http://comment.bilibili.com/{cid}.xml'
    danmaku_xml = ''
    danmaku_xml_tree = {}
    danmaku_pmf_data = {}
    headers = {
        'accept-encoding': 'gzip, deflate, sdch',
        'accept-language': 'en-CA,en;q=0.8,en-US;q=0.6,zh-CN;q=0.4,zh;q=0.2',
        'user-agent': '(Python-urllib/2.7, like libcurl/1.0 NSS-Mozilla/2.0)',
        'accept': '*/*',}
    chatserver = ''
    #self.chatid = 0
    mission = 0
    maxlimit = 0
    source = ''
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        pass
    #----------------------------------------------------------------------
    def init(self):
        """great init"""
        if  self.cid <= 0:
            raise ValueError('invalid cid')
        self.get()
        self.parse()
        pass
    @classmethod
    #----------------------------------------------------------------------
    def setcid(self, cid):
        """"""
        self.cid = cid
        self.danmaku_url = self.danmaku_url.format(cid = cid)
    #----------------------------------------------------------------------
    def get(self):
        """"""
        if not self.cid:
            raise ValueError('Cid not set')
        responce = requests.get(self.danmaku_url, headers= self.headers)
        self.danmaku_xml = responce.content
    @classmethod
    #----------------------------------------------------------------------
    def load(self, file_this):
        """"""
        if type(file_this) == str:
            self.danmaku_xml = file_this
        elif type(file_this) == file:
            f = open(file_this, 'r')
            self.danmaku_xml = f.read()
            f.close()
    #----------------------------------------------------------------------
    def parse(self):
        """"""
        if not self.danmaku_xml:
            raise ValueError('No Danmaku Data')
        tree = ET.ElementTree(ET.fromstring(self.danmaku_xml))
        root = tree.getroot()
        for child_of_root in root:
            if child_of_root.tag == 'chatserver':
                self.chatserver = child_of_root.text
            if child_of_root.tag == 'chatid':
                self.cid = int(child_of_root.text)
            if child_of_root.tag == 'mission':
                self.mission = child_of_root.text
            if child_of_root.tag == 'maxlimit':
                self.maxlimit = int(child_of_root.text)
            if child_of_root.tag == 'source':
                self.source = child_of_root.text
            if child_of_root.tag == 'd':
                info = str(child_of_root.attrib.get('p')).split(',')
                self.danmaku_xml_tree[info[7]] = {'stime': info[0],
                                                  'mode': info[1],
                                                  'size': info[2],
                                                  'color': info[3],
                                                  'timestamp': info[4],
                                                  'pool': info[5],
                                                  'sender': info[6],
                                                  'msg': child_of_root.text
                                                  }
    @classmethod
    #----------------------------------------------------------------------
    def get_pmf(self, period):
        """"""
        timelist = [(k, v['stime']) for k, v in self.danmaku_xml_tree.iteritems()]
        timelist.sort(key = lambda tup:tup[1])
        if period == 0:
            return timelist
        start = 0
        #not 0
        self.danmaku_pmf_data = {0: [], }
        for i in timelist:
            if i[1] <= int(start + period):
                self.danmaku_pmf_data[start].append(i[0])
            elif i[1] > int(start + period):
                start += period
                self.danmaku_pmf_data[start] = []
                self.danmaku_pmf_data[start].append(i[0])

 

关于与所谓Fuckbilibili项目关系的声明

      3 Comments on 关于与所谓Fuckbilibili项目关系的声明

我未专为Fuckbilibili项目开发过任何部分,亦不为其可能造成的任何不良后果负责。
截止声明时,Fuckbilibili网站所援引的的大量源码违反了GPL协议,所谓自行开发的源码违反了MIT协议。
请自行斟酌使用该项目中的任何部分。部分可能的后果会造成直接的人身、财产和/或名誉伤害。
Beining

Acfun黑科技:强制使用乐视源!垃圾画质吃屎去吧!

又及:
关于直接上传到乐视云:
参见

acupload 0.04:巨大更新


 
更新:我写插件了:
https://github.com/cnbeining/acfun-api-replace-server/tree/master/chrome
Acfun fix chrome 插件。
 
Chrome有很多插件,可以直接重定向请求。
我喜欢Switcheroo Redirector 。
加规则:

http://cdn.aixifan.com/player/sslhomura/AcNewPlayer151029.swf
重定向到
https://acfun-api.cnbeining.com/static/AcNewPlayer151029.swf

http://www.acfun.tv/video/getVideo.aspx?

https://acfun-api.cnbeining.com/getVideo?

服务端在Openshift,前面挂了CF。
懒得配置环境,人多了我也不知道怎样,随便吧。
服务端:https://github.com/cnbeining/acfun-api-replace-server
欢迎反馈。