mirror of
https://github.com/tgbot-collection/YYeTsBot.git
synced 2025-11-25 19:37:34 +08:00
class style, rename
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -110,6 +110,6 @@ venv.bak/
|
|||||||
/.idea/modules.xml
|
/.idea/modules.xml
|
||||||
/.idea/vcs.xml
|
/.idea/vcs.xml
|
||||||
.idea/
|
.idea/
|
||||||
/data/cookies.dump
|
/yyetsbot/data/cookies.dump
|
||||||
/.idea/inspectionProfiles/profiles_settings.xml
|
/.idea/inspectionProfiles/profiles_settings.xml
|
||||||
data/
|
yyetsbot/data/
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
dir to storage request id and data.
|
|
||||||
127
html_request.py
127
html_request.py
@@ -1,127 +0,0 @@
|
|||||||
# coding: utf-8
|
|
||||||
# YYeTsBot - html_request.py
|
|
||||||
# 2019/8/15 18:30
|
|
||||||
|
|
||||||
__author__ = 'Benny <benny.think@gmail.com>'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
import requests
|
|
||||||
import feedparser
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
|
|
||||||
from config import SEARCH_URL, GET_USER, RSS_URL, BASE_URL, SHARE_WEB, SHARE_URL, WORKERS, SHARE_API
|
|
||||||
from utils import load_cookies, cookie_file, login
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(filename)s [%(levelname)s]: %(message)s')
|
|
||||||
|
|
||||||
s = requests.Session()
|
|
||||||
ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
|
||||||
s.headers.update({"User-Agent": ua})
|
|
||||||
|
|
||||||
|
|
||||||
def get_search_html(kw: str) -> str:
|
|
||||||
if not os.path.exists(cookie_file):
|
|
||||||
logging.warning("Cookie file not found")
|
|
||||||
login()
|
|
||||||
if not is_cookie_valid():
|
|
||||||
login()
|
|
||||||
cookie = load_cookies()
|
|
||||||
logging.info("Searching for %s", kw)
|
|
||||||
r = s.get(SEARCH_URL.format(kw=kw), cookies=cookie)
|
|
||||||
|
|
||||||
r.close()
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
|
|
||||||
def get_detail_page(url: str) -> dict:
|
|
||||||
logging.info("Loading detail page %s", url)
|
|
||||||
share_link, api_res = analysis_share_page(url)
|
|
||||||
cnname = api_res["data"]["info"]["cnname"]
|
|
||||||
|
|
||||||
logging.info("Loading rss...")
|
|
||||||
rss_url = RSS_URL.format(id=url.split("/")[-1])
|
|
||||||
rss_result = analyse_rss(rss_url)
|
|
||||||
|
|
||||||
# get search_content from here...
|
|
||||||
if not rss_result:
|
|
||||||
rss_result = api_res
|
|
||||||
|
|
||||||
return {"all": rss_result, "share": share_link, "cnname": cnname}
|
|
||||||
|
|
||||||
|
|
||||||
def analyse_search_html(html: str) -> dict:
|
|
||||||
logging.info('Parsing html...')
|
|
||||||
soup = BeautifulSoup(html, 'lxml')
|
|
||||||
link_list = soup.find_all("div", class_="clearfix search-item")
|
|
||||||
list_result = {}
|
|
||||||
for block in link_list:
|
|
||||||
name = block.find_all('a')[-1].text
|
|
||||||
url = BASE_URL + block.find_all('a')[-1].attrs['href']
|
|
||||||
list_result[url] = name
|
|
||||||
|
|
||||||
return list_result
|
|
||||||
|
|
||||||
|
|
||||||
def analyse_rss(feed_url: str) -> dict:
|
|
||||||
# feed parser is meaningless now
|
|
||||||
return {}
|
|
||||||
# d = feedparser.parse(feed_url)
|
|
||||||
# # data['feed']['title']
|
|
||||||
# result = {}
|
|
||||||
# for item in d['entries']:
|
|
||||||
# download = {
|
|
||||||
# "title": getattr(item, "title", ""),
|
|
||||||
# "ed2k": getattr(item, "ed2k", ""),
|
|
||||||
# "magnet": getattr(item, "magnet", ""),
|
|
||||||
# "pan": getattr(item, "pan", "")}
|
|
||||||
# result[item.guid] = download
|
|
||||||
# return result
|
|
||||||
|
|
||||||
|
|
||||||
def analysis_share_page(detail_url: str) -> (str, dict):
|
|
||||||
rid = detail_url.split('/')[-1]
|
|
||||||
|
|
||||||
res = s.post(SHARE_URL, data={"rid": rid}, cookies=load_cookies()).json()
|
|
||||||
share_code = res['data'].split('/')[-1]
|
|
||||||
share_url = SHARE_WEB.format(code=share_code)
|
|
||||||
logging.info("Share url is %s", share_url)
|
|
||||||
|
|
||||||
# get api response
|
|
||||||
api_response = s.get(SHARE_API.format(code=share_code)).json()
|
|
||||||
return share_url, api_response
|
|
||||||
|
|
||||||
|
|
||||||
def is_cookie_valid() -> bool:
|
|
||||||
cookie = load_cookies()
|
|
||||||
r = s.get(GET_USER, cookies=cookie)
|
|
||||||
return r.json()['status'] == 1
|
|
||||||
|
|
||||||
|
|
||||||
def offline_search(search_content):
|
|
||||||
# from cloudflare workers
|
|
||||||
# no redis cache for now
|
|
||||||
logging.info("Loading data from cfkv...")
|
|
||||||
index = WORKERS.format(id="index")
|
|
||||||
data: dict = requests.get(index).json()
|
|
||||||
logging.info("Loading complete, searching now...")
|
|
||||||
|
|
||||||
results = {}
|
|
||||||
for name, rid in data.items():
|
|
||||||
if search_content in name:
|
|
||||||
fake_url = f"http://www.rrys2020.com/resource/{rid}"
|
|
||||||
results[fake_url] = name.replace("\n", " ")
|
|
||||||
logging.info("Search complete")
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
def offline_link(resource_url) -> str:
|
|
||||||
rid = resource_url.split("/")[-1]
|
|
||||||
query_url = WORKERS.format(id=rid)
|
|
||||||
# TODO: too lazy to optimize cloudflare worker page.
|
|
||||||
return query_url
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
a = offline_search("越狱")
|
|
||||||
print(a)
|
|
||||||
10
tests/test_fansub.py
Normal file
10
tests/test_fansub.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class MyTestCase(unittest.TestCase):
|
||||||
|
def test_something(self):
|
||||||
|
self.assertEqual(True, False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
@@ -1,329 +1,325 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
# YYeTsBot - bot.py
|
# YYeTsBot - bot.py
|
||||||
# 2019/8/15 18:27
|
# 2019/8/15 18:27
|
||||||
|
|
||||||
__author__ = 'Benny <benny.think@gmail.com>'
|
__author__ = 'Benny <benny.think@gmail.com>'
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from urllib.parse import quote_plus
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
import telebot
|
import telebot
|
||||||
from telebot import types, apihelper
|
from telebot import types, apihelper
|
||||||
from tgbot_ping import get_runtime
|
from tgbot_ping import get_runtime
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
from html_request import get_search_html, analyse_search_html, get_detail_page, offline_search, offline_link
|
from fansub import YYeTs
|
||||||
from utils import (save_error_dump, save_to_cache, yyets_get_from_cache, get_error_dump,
|
from utils import (save_error_dump, get_error_dump, reset_request, today_request,
|
||||||
reset_request, today_request, show_usage,
|
show_usage, redis_announcement
|
||||||
redis_announcement
|
)
|
||||||
)
|
from config import PROXY, TOKEN, SEARCH_URL, MAINTAINER, REPORT, OFFLINE
|
||||||
from config import PROXY, TOKEN, SEARCH_URL, MAINTAINER, REPORT, WORKERS, OFFLINE
|
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(filename)s [%(levelname)s]: %(message)s')
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(filename)s [%(levelname)s]: %(message)s')
|
if PROXY:
|
||||||
if PROXY:
|
apihelper.proxy = {'https': PROXY}
|
||||||
apihelper.proxy = {'https': PROXY}
|
|
||||||
|
bot = telebot.TeleBot(os.environ.get('TOKEN') or TOKEN)
|
||||||
bot = telebot.TeleBot(os.environ.get('TOKEN') or TOKEN)
|
angry_count = 0
|
||||||
angry_count = 0
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['start'])
|
||||||
@bot.message_handler(commands=['start'])
|
def send_welcome(message):
|
||||||
def send_welcome(message):
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
bot.send_message(message.chat.id, '欢迎使用,直接发送想要的剧集标题给我就可以了,不需要其他关键字,我会帮你搜索。\n\n'
|
||||||
bot.send_message(message.chat.id, '欢迎使用,直接发送想要的剧集标题给我就可以了,不需要其他关键字,我会帮你搜索。\n\n'
|
'人人影视专注于欧美日韩剧集,请不要反馈“我搜不到喜羊羊与灰太狼/流浪地球”这种问题,'
|
||||||
'人人影视专注于欧美日韩剧集,请不要反馈“我搜不到喜羊羊与灰太狼/流浪地球”这种问题,'
|
'我会生气的😠😡🤬😒\n\n'
|
||||||
'我会生气的😠😡🤬😒\n\n'
|
'建议使用<a href="http://www.zmz2019.com/">人人影视</a> 标准译名',
|
||||||
'建议使用<a href="http://www.zmz2019.com/">人人影视</a> 标准译名',
|
parse_mode='html', disable_web_page_preview=True)
|
||||||
parse_mode='html', disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['help'])
|
||||||
@bot.message_handler(commands=['help'])
|
def send_help(message):
|
||||||
def send_help(message):
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
bot.send_message(message.chat.id, '''机器人无法使用或者报错?从 /ping 里可以看到运行状态以及最新信息。
|
||||||
bot.send_message(message.chat.id, '''机器人无法使用或者报错?从 /ping 里可以看到运行状态以及最新信息。
|
同时,你可以使用如下方式寻求使用帮助和报告错误:\n
|
||||||
同时,你可以使用如下方式寻求使用帮助和报告错误:\n
|
1. @BennyThink
|
||||||
1. @BennyThink
|
2. <a href='https://github.com/BennyThink/YYeTsBot/issues'>Github issues</a>
|
||||||
2. <a href='https://github.com/BennyThink/YYeTsBot/issues'>Github issues</a>
|
3. <a href='https://t.me/mikuri520'>Telegram Channel</a>''', parse_mode='html', disable_web_page_preview=True)
|
||||||
3. <a href='https://t.me/mikuri520'>Telegram Channel</a>''', parse_mode='html', disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['ping'])
|
||||||
@bot.message_handler(commands=['ping'])
|
def send_ping(message):
|
||||||
def send_ping(message):
|
logging.info("Pong!")
|
||||||
logging.info("Pong!")
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
|
||||||
|
info = get_runtime("botsrunner_yyets_1")
|
||||||
info = get_runtime("botsrunner_yyets_1")
|
redis = get_runtime("botsrunner_redis_1", "Redis")
|
||||||
redis = get_runtime("botsrunner_redis_1", "Redis")
|
|
||||||
|
usage = ""
|
||||||
usage = ""
|
if str(message.chat.id) == MAINTAINER:
|
||||||
if str(message.chat.id) == MAINTAINER:
|
usage = show_usage()
|
||||||
usage = show_usage()
|
announcement = redis_announcement() or ""
|
||||||
announcement = redis_announcement() or ""
|
if announcement:
|
||||||
if announcement:
|
announcement = f"\n\n*公告:{announcement}*\n\n"
|
||||||
announcement = f"\n\n*公告:{announcement}*\n\n"
|
bot.send_message(message.chat.id, f"{info}\n{redis}\n\n{usage}\n{announcement}",
|
||||||
bot.send_message(message.chat.id, f"{info}\n{redis}\n\n{usage}\n{announcement}",
|
parse_mode='markdown')
|
||||||
parse_mode='markdown')
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['settings'])
|
||||||
@bot.message_handler(commands=['settings'])
|
def settings(message):
|
||||||
def settings(message):
|
is_admin = str(message.chat.id) == MAINTAINER
|
||||||
is_admin = str(message.chat.id) == MAINTAINER
|
# 普通用户只可以查看,不可以设置。
|
||||||
# 普通用户只可以查看,不可以设置。
|
# 管理员可以查看可以设置
|
||||||
# 管理员可以查看可以设置
|
if message.text != "/settings" and not is_admin:
|
||||||
if message.text != "/settings" and not is_admin:
|
bot.send_message(message.chat.id, "此功能只允许管理员使用。请使用 /ping 和 /settings 查看相关信息")
|
||||||
bot.send_message(message.chat.id, "此功能只允许管理员使用。请使用 /ping 和 /settings 查看相关信息")
|
return
|
||||||
return
|
|
||||||
|
# 删除公告,设置新公告
|
||||||
# 删除公告,设置新公告
|
if message.text != "/settings":
|
||||||
if message.text != "/settings":
|
date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
text = message.text.replace("/settings", f"{date}\t")
|
||||||
text = message.text.replace("/settings", f"{date}\t")
|
logging.info("New announcement %s", text)
|
||||||
logging.info("New announcement %s", text)
|
redis_announcement(text, "set")
|
||||||
redis_announcement(text, "set")
|
setattr(message, "text", "/settings")
|
||||||
setattr(message, "text", "/settings")
|
settings(message)
|
||||||
settings(message)
|
return
|
||||||
return
|
|
||||||
|
announcement = redis_announcement()
|
||||||
announcement = redis_announcement()
|
markup = types.InlineKeyboardMarkup()
|
||||||
markup = types.InlineKeyboardMarkup()
|
btn1 = types.InlineKeyboardButton("删除公告", callback_data="announcement")
|
||||||
btn1 = types.InlineKeyboardButton("删除公告", callback_data="announcement")
|
if is_admin and announcement:
|
||||||
if is_admin and announcement:
|
markup.add(btn1)
|
||||||
markup.add(btn1)
|
|
||||||
|
bot.send_message(message.chat.id, f"目前公告:\n\n {announcement or '暂无公告'}", reply_markup=markup)
|
||||||
bot.send_message(message.chat.id, f"目前公告:\n\n {announcement or '暂无公告'}", reply_markup=markup)
|
|
||||||
|
|
||||||
|
@bot.callback_query_handler(func=lambda call: re.findall(r"announcement(\S*)", call.data))
|
||||||
@bot.callback_query_handler(func=lambda call: re.findall(r"announcement(\S*)", call.data))
|
def delete_announcement(call):
|
||||||
def delete_announcement(call):
|
bot.send_chat_action(call.message.chat.id, 'typing')
|
||||||
bot.send_chat_action(call.message.chat.id, 'typing')
|
redis_announcement(op="del")
|
||||||
redis_announcement(op="del")
|
|
||||||
|
bot.edit_message_text(f"目前公告:\n\n {redis_announcement() or '暂无公告'}",
|
||||||
bot.edit_message_text(f"目前公告:\n\n {redis_announcement() or '暂无公告'}",
|
call.message.chat.id,
|
||||||
call.message.chat.id,
|
call.message.message_id)
|
||||||
call.message.message_id)
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['credits'])
|
||||||
@bot.message_handler(commands=['credits'])
|
def send_credits(message):
|
||||||
def send_credits(message):
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
bot.send_message(message.chat.id, '''感谢字幕组的无私奉献!本机器人资源来源:\n
|
||||||
bot.send_message(message.chat.id, '''感谢字幕组的无私奉献!本机器人资源来源:\n
|
<a href="http://www.zmz2019.com/">人人影视</a>
|
||||||
<a href="http://www.zmz2019.com/">人人影视</a>
|
<a href="http://cili001.com/">磁力下载站</a>
|
||||||
<a href="http://cili001.com/">磁力下载站</a>
|
<a href="http://www.zhuixinfan.com/main.php">追新番</a>
|
||||||
<a href="http://www.zhuixinfan.com/main.php">追新番</a>
|
''', parse_mode='html', disable_web_page_preview=True)
|
||||||
''', parse_mode='html', disable_web_page_preview=True)
|
|
||||||
|
|
||||||
|
def download_to_io(photo):
|
||||||
def download_to_io(photo):
|
logging.info("Initializing bytes io...")
|
||||||
logging.info("Initializing bytes io...")
|
mem = io.BytesIO()
|
||||||
mem = io.BytesIO()
|
file_id = photo[-1].file_id
|
||||||
file_id = photo[-1].file_id
|
logging.info("Downloading photos...")
|
||||||
logging.info("Downloading photos...")
|
file_info = bot.get_file(file_id)
|
||||||
file_info = bot.get_file(file_id)
|
content = bot.download_file(file_info.file_path)
|
||||||
content = bot.download_file(file_info.file_path)
|
mem.write(content)
|
||||||
mem.write(content)
|
logging.info("Downloading complete.")
|
||||||
logging.info("Downloading complete.")
|
return mem
|
||||||
return mem
|
|
||||||
|
|
||||||
|
def send_my_response(message):
|
||||||
def send_my_response(message):
|
bot.send_chat_action(message.chat.id, 'record_video_note')
|
||||||
bot.send_chat_action(message.chat.id, 'record_video_note')
|
# I may also send picture
|
||||||
# I may also send picture
|
photo = message.photo
|
||||||
photo = message.photo
|
uid = message.reply_to_message.caption
|
||||||
uid = message.reply_to_message.caption
|
text = f"主人说:{message.text or message.caption or '啥也没说😯'}"
|
||||||
text = f"主人说:{message.text or message.caption or '啥也没说😯'}"
|
if photo:
|
||||||
if photo:
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
logging.info("Photo received from maintainer")
|
||||||
logging.info("Photo received from maintainer")
|
mem = download_to_io(photo)
|
||||||
mem = download_to_io(photo)
|
mem.name = f'{uid}.jpg'
|
||||||
mem.name = f'{uid}.jpg'
|
r = bot.send_photo(uid, mem.getvalue(), caption=text)
|
||||||
r = bot.send_photo(uid, mem.getvalue(), caption=text)
|
else:
|
||||||
else:
|
r = bot.send_message(uid, text)
|
||||||
r = bot.send_message(uid, text)
|
|
||||||
|
logging.info("Reply has been sent to %s with message id %s", uid, r.message_id)
|
||||||
logging.info("Reply has been sent to %s with message id %s", uid, r.message_id)
|
bot.reply_to(message, "回复已经发送给这位用户")
|
||||||
bot.reply_to(message, "回复已经发送给这位用户")
|
fw = bot.forward_message(message.chat.id, uid, r.message_id)
|
||||||
fw = bot.forward_message(message.chat.id, uid, r.message_id)
|
time.sleep(3)
|
||||||
time.sleep(3)
|
bot.delete_message(message.chat.id, fw.message_id)
|
||||||
bot.delete_message(message.chat.id, fw.message_id)
|
logging.info("Forward has been deleted.")
|
||||||
logging.info("Forward has been deleted.")
|
|
||||||
|
|
||||||
|
@bot.message_handler(content_types=["photo", "text"])
|
||||||
@bot.message_handler(content_types=["photo", "text"])
|
def send_search(message):
|
||||||
def send_search(message):
|
yyets = YYeTs()
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
|
|
||||||
today_request("total")
|
today_request("total")
|
||||||
if message.reply_to_message and message.reply_to_message.document and \
|
if message.reply_to_message and message.reply_to_message.document and \
|
||||||
message.reply_to_message.document.file_name.startswith("error") and str(message.chat.id) == MAINTAINER:
|
message.reply_to_message.document.file_name.startswith("error") and str(message.chat.id) == MAINTAINER:
|
||||||
today_request("answer")
|
today_request("answer")
|
||||||
send_my_response(message)
|
send_my_response(message)
|
||||||
return
|
return
|
||||||
|
|
||||||
name = message.text
|
name = message.text
|
||||||
logging.info('Receiving message: %s from user %s(%s)', name, message.chat.username, message.chat.id)
|
logging.info('Receiving message: %s from user %s(%s)', name, message.chat.username, message.chat.id)
|
||||||
if name is None:
|
if name is None:
|
||||||
today_request("invalid")
|
today_request("invalid")
|
||||||
with open('assets/warning.webp', 'rb') as sti:
|
with open('warning.webp', 'rb') as sti:
|
||||||
bot.send_message(message.chat.id, "不要调戏我!我会报警的")
|
bot.send_message(message.chat.id, "不要调戏我!我会报警的")
|
||||||
bot.send_sticker(message.chat.id, sti)
|
bot.send_sticker(message.chat.id, sti)
|
||||||
return
|
return
|
||||||
|
|
||||||
if OFFLINE:
|
if OFFLINE:
|
||||||
logging.warning("☢️ Going offline mode!!!")
|
logging.warning("☢️ Going offline mode!!!")
|
||||||
bot.send_message(message.chat.id, "人人影视官网不可用,目前在使用离线模式,可能没有最新的剧集。")
|
bot.send_message(message.chat.id, "人人影视官网不可用,目前在使用离线模式,可能没有最新的剧集。")
|
||||||
html = ""
|
bot.send_chat_action(message.chat.id, 'upload_document')
|
||||||
bot.send_chat_action(message.chat.id, 'upload_document')
|
result = yyets.offline_search_preview(name)
|
||||||
result = offline_search(name)
|
else:
|
||||||
else:
|
result = yyets.online_search_preview(name)
|
||||||
html = get_search_html(name)
|
|
||||||
result = analyse_search_html(html)
|
markup = types.InlineKeyboardMarkup()
|
||||||
|
for url, detail in result.items():
|
||||||
markup = types.InlineKeyboardMarkup()
|
btn = types.InlineKeyboardButton(detail, callback_data="choose%s" % url)
|
||||||
for url, detail in result.items():
|
markup.add(btn)
|
||||||
btn = types.InlineKeyboardButton(detail, callback_data="choose%s" % url)
|
|
||||||
markup.add(btn)
|
if result:
|
||||||
|
logging.info("🎉 Resource match.")
|
||||||
if result:
|
today_request("success")
|
||||||
logging.info("🎉 Resource match.")
|
bot.send_message(message.chat.id, "呐,💐🌷🌹选一个呀!", reply_markup=markup)
|
||||||
today_request("success")
|
else:
|
||||||
bot.send_message(message.chat.id, "呐,💐🌷🌹选一个呀!", reply_markup=markup)
|
logging.warning("⚠️️ Resource not found")
|
||||||
else:
|
today_request("fail")
|
||||||
logging.warning("⚠️️ Resource not found")
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
today_request("fail")
|
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
encoded = quote_plus(name)
|
||||||
|
bot.send_message(message.chat.id, f"没有找到你想要的信息,是不是你打了错别字,或者搜索了一些国产影视剧。🤪\n"
|
||||||
encoded = quote_plus(name)
|
f"还是你想调戏我哦🙅️\n\n"
|
||||||
bot.send_message(message.chat.id, f"没有找到你想要的信息,是不是你打了错别字,或者搜索了一些国产影视剧。🤪\n"
|
f"可以看看这个链接,看看有没有结果。 {SEARCH_URL.format(kw=encoded)} \n\n"
|
||||||
f"还是你想调戏我哦🙅️\n\n"
|
"⚠️如果确定要我背锅,那么请使用 /help 来提交错误", disable_web_page_preview=True)
|
||||||
f"可以看看这个链接,看看有没有结果。 {SEARCH_URL.format(kw=encoded)} \n\n"
|
if REPORT:
|
||||||
"⚠️如果确定要我背锅,那么请使用 /help 来提交错误", disable_web_page_preview=True)
|
btn = types.InlineKeyboardButton("快来修复啦", callback_data="fix")
|
||||||
if REPORT:
|
markup.add(btn)
|
||||||
btn = types.InlineKeyboardButton("快来修复啦", callback_data="fix")
|
bot.send_chat_action(message.chat.id, 'upload_document')
|
||||||
markup.add(btn)
|
bot.send_message(message.chat.id, f"《{name}》😭\n大部分情况下机器人是好用的,不要怀疑我的代码质量.\n"
|
||||||
bot.send_chat_action(message.chat.id, 'upload_document')
|
f"如果你真的确定是机器人出问题了,那么点下面的按钮叫 @BennyThink 来修!\n"
|
||||||
bot.send_message(message.chat.id, f"《{name}》😭\n大部分情况下机器人是好用的,不要怀疑我的代码质量.\n"
|
f"⚠️报错前请三思,不要乱点,确保这锅应该甩给我。否则我会很生气的😡小心被拉黑哦",
|
||||||
f"如果你真的确定是机器人出问题了,那么点下面的按钮叫 @BennyThink 来修!\n"
|
reply_markup=markup)
|
||||||
f"⚠️报错前请三思,不要乱点,确保这锅应该甩给我。否则我会很生气的😡小心被拉黑哦",
|
content = f""" 报告者:{message.chat.first_name}{message.chat.last_name or ""}@{message.chat.username or ""}({message.chat.id})
|
||||||
reply_markup=markup)
|
问题发生时间:{time.strftime("%Y-%m-%data %H:%M:%S", time.localtime(message.date))}
|
||||||
content = f""" 报告者:{message.chat.first_name}{message.chat.last_name or ""}@{message.chat.username or ""}({message.chat.id})
|
请求内容:{name}
|
||||||
问题发生时间:{time.strftime("%Y-%m-%data %H:%M:%S", time.localtime(message.date))}
|
请求URL:{SEARCH_URL.format(kw=encoded)}\n\n
|
||||||
请求内容:{name}
|
|
||||||
请求URL:{SEARCH_URL.format(kw=encoded)}\n\n
|
"""
|
||||||
返回内容:{html}
|
save_error_dump(message.chat.id, content)
|
||||||
"""
|
|
||||||
save_error_dump(message.chat.id, content)
|
|
||||||
|
@bot.callback_query_handler(func=lambda call: re.findall(r"choose(\S*)", call.data))
|
||||||
|
def choose_link(call):
|
||||||
@bot.callback_query_handler(func=lambda call: re.findall(r"choose(\S*)", call.data))
|
yyets = YYeTs()
|
||||||
def choose_link(call):
|
bot.send_chat_action(call.message.chat.id, 'typing')
|
||||||
bot.send_chat_action(call.message.chat.id, 'typing')
|
# call.data is url, http://www.rrys2020.com/resource/36588
|
||||||
# call.data is url, http://www.rrys2020.com/resource/36588
|
resource_url = re.findall(r"choose(\S*)", call.data)[0]
|
||||||
resource_url = re.findall(r"choose(\S*)", call.data)[0]
|
markup = types.InlineKeyboardMarkup()
|
||||||
markup = types.InlineKeyboardMarkup()
|
|
||||||
|
if OFFLINE:
|
||||||
if OFFLINE:
|
worker_page = yyets.offline_search_result(resource_url)
|
||||||
worker_page = offline_link(resource_url)
|
btn1 = types.InlineKeyboardButton("打开网页", url=worker_page)
|
||||||
btn1 = types.InlineKeyboardButton("打开网页", url=worker_page)
|
markup.add(btn1)
|
||||||
markup.add(btn1)
|
bot.send_message(call.message.chat.id, "离线模式,点击按钮打开网页获取结果", reply_markup=markup)
|
||||||
bot.send_message(call.message.chat.id, "离线模式,点击按钮打开网页获取结果", reply_markup=markup)
|
return
|
||||||
return
|
|
||||||
|
btn1 = types.InlineKeyboardButton("分享页面", callback_data="share%s" % resource_url)
|
||||||
link = yyets_get_from_cache(resource_url)
|
btn2 = types.InlineKeyboardButton("我全都要", callback_data="all%s" % resource_url)
|
||||||
if not link:
|
markup.add(btn1, btn2)
|
||||||
link = get_detail_page(resource_url)
|
text = "想要分享页面,还是我全都要?\n\n" \
|
||||||
save_to_cache(resource_url, link)
|
"名词解释:“分享页面”会返回给你一个网站,从那里可以看到全部的下载链接。\n" \
|
||||||
|
"“我全都要”会给你发送一个txt文件,文件里包含全部下载连接\n"
|
||||||
btn1 = types.InlineKeyboardButton("分享页面", callback_data="share%s" % resource_url)
|
bot.send_message(call.message.chat.id, text, reply_markup=markup)
|
||||||
btn2 = types.InlineKeyboardButton("我全都要", callback_data="all%s" % resource_url)
|
|
||||||
markup.add(btn1, btn2)
|
|
||||||
text = "想要分享页面,还是我全都要?\n\n" \
|
@bot.callback_query_handler(func=lambda call: re.findall(r"share(\S*)", call.data))
|
||||||
"名词解释:“分享页面”会返回给你一个网站,从那里可以看到全部的下载链接。\n" \
|
def share_page(call):
|
||||||
"“我全都要”会给你发送一个txt文件,文件里包含全部下载连接\n"
|
yyets = YYeTs()
|
||||||
bot.send_message(call.message.chat.id, text, reply_markup=markup)
|
bot.send_chat_action(call.message.chat.id, 'typing')
|
||||||
|
resource_url = re.findall(r"share(\S*)", call.data)[0]
|
||||||
|
result = yyets.online_search_result(resource_url)
|
||||||
@bot.callback_query_handler(func=lambda call: re.findall(r"share(\S*)", call.data))
|
bot.send_message(call.message.chat.id, result['share'])
|
||||||
def share_page(call):
|
|
||||||
bot.send_chat_action(call.message.chat.id, 'typing')
|
|
||||||
resource_url = re.findall(r"share(\S*)", call.data)[0]
|
@bot.callback_query_handler(func=lambda call: re.findall(r"all(\S*)", call.data))
|
||||||
result = yyets_get_from_cache(resource_url)
|
def all_episode(call):
|
||||||
bot.send_message(call.message.chat.id, result['share'])
|
# just send a file
|
||||||
|
yyets = YYeTs()
|
||||||
|
bot.send_chat_action(call.message.chat.id, 'typing')
|
||||||
@bot.callback_query_handler(func=lambda call: re.findall(r"all(\S*)", call.data))
|
resource_url = re.findall(r"all(\S*)", call.data)[0]
|
||||||
def all_episode(call):
|
result = yyets.online_search_result(resource_url)
|
||||||
# just send a file
|
|
||||||
bot.send_chat_action(call.message.chat.id, 'typing')
|
with tempfile.NamedTemporaryFile(mode='wb+', prefix=result["cnname"], suffix=".txt") as tmp:
|
||||||
resource_url = re.findall(r"all(\S*)", call.data)[0]
|
bytes_data = json.dumps(result["all"], ensure_ascii=False, indent=4).encode('u8')
|
||||||
result = yyets_get_from_cache(resource_url)
|
tmp.write(bytes_data)
|
||||||
|
tmp.flush()
|
||||||
with tempfile.NamedTemporaryFile(mode='wb+', prefix=result["cnname"], suffix=".txt") as tmp:
|
with open(tmp.name, "rb") as f:
|
||||||
bytes_data = json.dumps(result["all"], ensure_ascii=False, indent=4).encode('u8')
|
bot.send_chat_action(call.message.chat.id, 'upload_document')
|
||||||
tmp.write(bytes_data)
|
bot.send_document(call.message.chat.id, f)
|
||||||
tmp.flush()
|
|
||||||
with open(tmp.name, "rb") as f:
|
|
||||||
bot.send_chat_action(call.message.chat.id, 'upload_document')
|
@bot.callback_query_handler(func=lambda call: re.findall(r"unwelcome(\d*)", call.data))
|
||||||
bot.send_document(call.message.chat.id, f)
|
def send_unwelcome(call):
|
||||||
|
# this will come from me only
|
||||||
|
logging.warning("I'm so unhappy!")
|
||||||
@bot.callback_query_handler(func=lambda call: re.findall(r"unwelcome(\d*)", call.data))
|
message = call.message
|
||||||
def send_unwelcome(call):
|
bot.send_chat_action(message.chat.id, 'typing')
|
||||||
# this will come from me only
|
|
||||||
logging.warning("I'm so unhappy!")
|
# angry_count = angry_count + 1
|
||||||
message = call.message
|
global angry_count
|
||||||
bot.send_chat_action(message.chat.id, 'typing')
|
angry_count += 1
|
||||||
|
uid = re.findall(r"unwelcome(\d*)", call.data)[0]
|
||||||
# angry_count = angry_count + 1
|
|
||||||
global angry_count
|
if uid:
|
||||||
angry_count += 1
|
text = "人人影视主要提供欧美日韩等海外资源,你的这个真没有🤷。\n" \
|
||||||
uid = re.findall(r"unwelcome(\d*)", call.data)[0]
|
"<b>麻烦你先从自己身上找原因</b>,我又不是你的专属客服。\n" \
|
||||||
|
"不要再报告这种错误了🙄️,面倒な。😡"
|
||||||
if uid:
|
bot.send_message(uid, text, parse_mode="html")
|
||||||
text = "人人影视主要提供欧美日韩等海外资源,你的这个真没有🤷。\n" \
|
bot.reply_to(message, f"有生之日 生气次数:{angry_count}")
|
||||||
"<b>麻烦你先从自己身上找原因</b>,我又不是你的专属客服。\n" \
|
|
||||||
"不要再报告这种错误了🙄️,面倒な。😡"
|
|
||||||
bot.send_message(uid, text, parse_mode="html")
|
@bot.callback_query_handler(func=lambda call: call.data == 'fix')
|
||||||
bot.reply_to(message, f"有生之日 生气次数:{angry_count}")
|
def report_error(call):
|
||||||
|
logging.error("Reporting error to maintainer.")
|
||||||
|
bot.send_chat_action(call.message.chat.id, 'typing')
|
||||||
@bot.callback_query_handler(func=lambda call: call.data == 'fix')
|
error_content = get_error_dump(call.message.chat.id)
|
||||||
def report_error(call):
|
if error_content == "":
|
||||||
logging.error("Reporting error to maintainer.")
|
bot.answer_callback_query(call.id, '多次汇报重复的问题并不会加快处理速度。', show_alert=True)
|
||||||
bot.send_chat_action(call.message.chat.id, 'typing')
|
return
|
||||||
error_content = get_error_dump(call.message.chat.id)
|
|
||||||
if error_content == "":
|
text = f'人人影视机器人似乎出现了一些问题🤔🤔🤔……{error_content[0:300]}'
|
||||||
bot.answer_callback_query(call.id, '多次汇报重复的问题并不会加快处理速度。', show_alert=True)
|
|
||||||
return
|
markup = types.InlineKeyboardMarkup()
|
||||||
|
btn = types.InlineKeyboardButton("unwelcome", callback_data=f"unwelcome{call.message.chat.id}")
|
||||||
text = f'人人影视机器人似乎出现了一些问题🤔🤔🤔……{error_content[0:300]}'
|
markup.add(btn)
|
||||||
|
|
||||||
markup = types.InlineKeyboardMarkup()
|
bot.send_message(MAINTAINER, text, disable_web_page_preview=True, reply_markup=markup)
|
||||||
btn = types.InlineKeyboardButton("unwelcome", callback_data=f"unwelcome{call.message.chat.id}")
|
|
||||||
markup.add(btn)
|
with tempfile.NamedTemporaryFile(mode='wb+', prefix=f"error_{call.message.chat.id}_", suffix=".txt") as tmp:
|
||||||
|
tmp.write(error_content.encode('u8'))
|
||||||
bot.send_message(MAINTAINER, text, disable_web_page_preview=True, reply_markup=markup)
|
tmp.flush()
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(mode='wb+', prefix=f"error_{call.message.chat.id}_", suffix=".txt") as tmp:
|
with open(tmp.name, "rb") as f:
|
||||||
tmp.write(error_content.encode('u8'))
|
bot.send_chat_action(call.message.chat.id, 'upload_document')
|
||||||
tmp.flush()
|
bot.send_document(MAINTAINER, f, caption=str(call.message.chat.id))
|
||||||
|
|
||||||
with open(tmp.name, "rb") as f:
|
bot.answer_callback_query(call.id, 'Debug信息已经发送给维护者,请耐心等待回复~', show_alert=True)
|
||||||
bot.send_chat_action(call.message.chat.id, 'upload_document')
|
|
||||||
bot.send_document(MAINTAINER, f, caption=str(call.message.chat.id))
|
|
||||||
|
if __name__ == '__main__':
|
||||||
bot.answer_callback_query(call.id, 'Debug信息已经发送给维护者,请耐心等待回复~', show_alert=True)
|
logging.info('YYeTs bot is running...')
|
||||||
|
scheduler = BackgroundScheduler()
|
||||||
|
scheduler.add_job(reset_request, 'cron', hour=0, minute=0)
|
||||||
if __name__ == '__main__':
|
scheduler.start()
|
||||||
logging.info('YYeTs bot is running...')
|
bot.polling(none_stop=True)
|
||||||
scheduler = BackgroundScheduler()
|
|
||||||
scheduler.add_job(reset_request, 'cron', hour=0, minute=0)
|
|
||||||
scheduler.start()
|
|
||||||
bot.polling(none_stop=True)
|
|
||||||
@@ -1,30 +1,31 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
# YYeTsBot - config.py
|
# YYeTsBot - config.py
|
||||||
# 2019/8/15 18:42
|
# 2019/8/15 18:42
|
||||||
|
|
||||||
__author__ = 'Benny <benny.think@gmail.com>'
|
__author__ = 'Benny <benny.think@gmail.com>'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
BASE_URL = "http://www.rrys2020.com"
|
BASE_URL = "http://www.rrys2020.com"
|
||||||
LOGIN_URL = "http://www.rrys2020.com/user/login"
|
LOGIN_URL = "http://www.rrys2020.com/user/login"
|
||||||
GET_USER = "http://www.rrys2020.com/user/login/getCurUserTopInfo"
|
GET_USER = "http://www.rrys2020.com/user/login/getCurUserTopInfo"
|
||||||
# rss is unavailable as of 2021.01.10
|
SEARCH_URL = "http://www.rrys2020.com/search?keyword={kw}&type=resource"
|
||||||
RSS_URL = "http://rss.rrys.tv/rss/feed/{id}"
|
AJAX_LOGIN = "http://www.rrys2020.com/User/Login/ajaxLogin"
|
||||||
SEARCH_URL = "http://www.rrys2020.com/search?keyword={kw}&type=resource"
|
SHARE_URL = "http://www.rrys2020.com/resource/ushare"
|
||||||
AJAX_LOGIN = "http://www.rrys2020.com/User/Login/ajaxLogin"
|
SHARE_WEB = "http://got002.com/resource.html?code={code}"
|
||||||
SHARE_URL = "http://www.rrys2020.com/resource/ushare"
|
# http://got002.com/api/v1/static/resource/detail?code=9YxN91
|
||||||
SHARE_WEB = "http://got002.com/resource.html?code={code}"
|
SHARE_API = "http://got002.com/api/v1/static/resource/detail?code={code}"
|
||||||
# http://got002.com/api/v1/static/resource/detail?code=9YxN91
|
|
||||||
SHARE_API = "http://got002.com/api/v1/static/resource/detail?code={code}"
|
WORKERS = "https://yyets.yyetsdb.workers.dev/?id={id}"
|
||||||
|
|
||||||
WORKERS = "https://yyets.yyetsdb.workers.dev/?id={id}"
|
TOKEN = os.environ.get("TOKEN") or "TOKEN"
|
||||||
|
USERNAME = os.environ.get("USERNAME") or "USERNAME"
|
||||||
TOKEN = os.environ.get("TOKEN") or "TOKEN"
|
PASSWORD = os.environ.get("PASSWORD") or "password"
|
||||||
USERNAME = os.environ.get("USERNAME") or "USERNAME"
|
PROXY = os.environ.get("PROXY")
|
||||||
PASSWORD = os.environ.get("PASSWORD") or "password"
|
MAINTAINER = os.environ.get("MAINTAINER")
|
||||||
PROXY = os.environ.get("PROXY")
|
REDIS = os.environ.get("REDIS") or "redis"
|
||||||
MAINTAINER = os.environ.get("MAINTAINER")
|
REPORT = os.environ.get("REPORT") or False
|
||||||
REDIS = os.environ.get("REDIS") or "redis"
|
OFFLINE = os.environ.get("OFFLINE") or False
|
||||||
REPORT = os.environ.get("REPORT") or False
|
|
||||||
OFFLINE = os.environ.get("OFFLINE") or False
|
FIX_RESOURCE = "https://www.zimuxia.cn/portfolio/{name}"
|
||||||
|
FIX_SEARCH = "https://www.zimuxia.cn/?s={name}"
|
||||||
233
yyetsbot/fansub.py
Normal file
233
yyetsbot/fansub.py
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
# YYeTsBot - fansub.py
|
||||||
|
# 2019/8/15 18:30
|
||||||
|
|
||||||
|
__author__ = 'Benny <benny.think@gmail.com>'
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
import pickle
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from config import (SEARCH_URL, GET_USER, BASE_URL, SHARE_WEB,
|
||||||
|
SHARE_URL, WORKERS, SHARE_API, USERNAME, PASSWORD,
|
||||||
|
AJAX_LOGIN, REDIS)
|
||||||
|
import redis
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(filename)s [%(levelname)s]: %(message)s')
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
|
||||||
|
session.headers.update({"User-Agent": ua})
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFansub:
|
||||||
|
"""
|
||||||
|
all the subclass should implement three kinds of methods:
|
||||||
|
1. online search, contains preview for bot and complete result
|
||||||
|
2. offline search (set pass if not applicable)
|
||||||
|
3. login and check (set pass if not applicable)
|
||||||
|
4. search_result this is critical for bot to draw markup
|
||||||
|
|
||||||
|
"""
|
||||||
|
label = None
|
||||||
|
cookie_file = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.data = None
|
||||||
|
self.url = None
|
||||||
|
self.redis = redis.StrictRedis(host=REDIS, decode_responses=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
# implement how to get the unique id for this resource
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __get_search_html__(self, kw: str) -> str:
|
||||||
|
# return html text of search page
|
||||||
|
pass
|
||||||
|
|
||||||
|
def online_search_preview(self, search_text: str) -> dict:
|
||||||
|
# try to retrieve critical information from html
|
||||||
|
# this result must return to bot for manual selection
|
||||||
|
# {"url1": "name1", "url2": "name2"}
|
||||||
|
pass
|
||||||
|
|
||||||
|
def online_search_result(self, resource_url: str) -> dict:
|
||||||
|
"""
|
||||||
|
This will happen when user click one of the button, only by then we can know the resource link
|
||||||
|
From the information above, try to get a detail dict structure.
|
||||||
|
This method should check cache first if applicable
|
||||||
|
This method should set self.link and self.data
|
||||||
|
This method should call __execute_online_search
|
||||||
|
:param resource_url:
|
||||||
|
:return: {"all": rss_result, "share": share_link, "cnname": cnname}
|
||||||
|
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __execute_online_search_result(self) -> dict:
|
||||||
|
"""
|
||||||
|
Do the real search job, without any cache mechanism
|
||||||
|
:return: {"all": rss_result, "share": share_link, "cnname": cnname}
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def offline_search_preview(self, search_text: str) -> dict:
|
||||||
|
# this result must return to bot for manual selection
|
||||||
|
# the same as online
|
||||||
|
pass
|
||||||
|
|
||||||
|
def offline_search_result(self, resource_url) -> dict:
|
||||||
|
"""
|
||||||
|
Same as online_search_result
|
||||||
|
:param resource_url:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __execute_offline_search_result(self) -> dict:
|
||||||
|
"""
|
||||||
|
Do the search job, without any cache mechanism
|
||||||
|
:return: {"all": rss_result, "share": share_link, "cnname": cnname}
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __login_check(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __manual_login(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __save_cookies(self, requests_cookiejar):
|
||||||
|
with open(self.cookie_file, 'wb') as f:
|
||||||
|
pickle.dump(requests_cookiejar, f)
|
||||||
|
|
||||||
|
def __load_cookies(self):
|
||||||
|
with open(self.cookie_file, 'rb') as f:
|
||||||
|
return pickle.load(f)
|
||||||
|
|
||||||
|
def __get_from_cache(self, url: str, method_name: str) -> dict:
|
||||||
|
logging.info("Reading %s data from cache %s", self.label, url)
|
||||||
|
data = self.redis.get(url)
|
||||||
|
if data:
|
||||||
|
logging.info("Cache hit")
|
||||||
|
return json.loads(data)
|
||||||
|
else:
|
||||||
|
logging.info("Cache miss")
|
||||||
|
result_method = getattr(self, method_name)
|
||||||
|
self.__save_to_cache(url, result_method(url))
|
||||||
|
return self.__get_from_cache(url, method_name)
|
||||||
|
|
||||||
|
def __save_to_cache(self, url: str, value: dict, ex=3600 * 12) -> None:
|
||||||
|
data = json.dumps(value, ensure_ascii=False)
|
||||||
|
self.redis.set(url, data, ex=ex)
|
||||||
|
|
||||||
|
|
||||||
|
class YYeTs(BaseFansub):
|
||||||
|
label = "yyets"
|
||||||
|
cookie_file = os.path.join("data", "cookies.dump")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
# implement how to get the unique id for this resource
|
||||||
|
rid = self.url.split('/')[-1]
|
||||||
|
return rid
|
||||||
|
|
||||||
|
def __get_search_html__(self, kw: str) -> str:
|
||||||
|
self.__login_check()
|
||||||
|
cookie = self.__load_cookies()
|
||||||
|
logging.info("Searching for %s", kw)
|
||||||
|
r = session.get(SEARCH_URL.format(kw=kw), cookies=cookie)
|
||||||
|
r.close()
|
||||||
|
return r.text
|
||||||
|
|
||||||
|
def online_search_preview(self, search_text: str) -> dict:
|
||||||
|
html_text = self.__get_search_html__(search_text)
|
||||||
|
logging.info('Parsing html...')
|
||||||
|
soup = BeautifulSoup(html_text, 'lxml')
|
||||||
|
link_list = soup.find_all("div", class_="clearfix search-item")
|
||||||
|
dict_result = {}
|
||||||
|
for block in link_list:
|
||||||
|
name = block.find_all('a')[-1].text
|
||||||
|
url = BASE_URL + block.find_all('a')[-1].attrs['href']
|
||||||
|
dict_result[url] = name
|
||||||
|
|
||||||
|
return dict_result
|
||||||
|
|
||||||
|
def online_search_result(self, resource_url: str) -> dict:
|
||||||
|
self.url = resource_url
|
||||||
|
self.data = self.__get_from_cache(self.url, self.__execute_online_search_result.__name__)
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def __execute_online_search_result(self) -> dict:
|
||||||
|
logging.info("Loading detail page %s", self.url)
|
||||||
|
share_link, api_res = self.__get_share_page()
|
||||||
|
cnname = api_res["data"]["info"]["cnname"]
|
||||||
|
self.data = {"all": api_res, "share": share_link, "cnname": cnname}
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def offline_search_preview(self, search_text: str) -> dict:
|
||||||
|
# from cloudflare workers
|
||||||
|
# no redis cache for now
|
||||||
|
logging.info("Loading data from cfkv...")
|
||||||
|
index = WORKERS.format(id="index")
|
||||||
|
data: dict = requests.get(index).json()
|
||||||
|
logging.info("Loading complete, searching now...")
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
for name, rid in data.items():
|
||||||
|
if search_text in name:
|
||||||
|
fake_url = f"http://www.rrys2020.com/resource/{rid}"
|
||||||
|
results[fake_url] = name.replace("\n", " ")
|
||||||
|
logging.info("Search complete")
|
||||||
|
return results
|
||||||
|
|
||||||
|
def offline_search_result(self, resource_url) -> dict:
|
||||||
|
self.url = resource_url
|
||||||
|
query_url = WORKERS.format(id=self.id)
|
||||||
|
self.data = {"all": None, "share": query_url, "cnname": None}
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def __login_check(self):
|
||||||
|
if not os.path.exists(self.cookie_file):
|
||||||
|
logging.warning("Cookie file not found")
|
||||||
|
self.__manual_login()
|
||||||
|
|
||||||
|
cookie = self.__load_cookies()
|
||||||
|
r = session.get(GET_USER, cookies=cookie)
|
||||||
|
if not r.json()['status'] == 1:
|
||||||
|
self.__manual_login()
|
||||||
|
|
||||||
|
def __manual_login(self):
|
||||||
|
data = {"account": USERNAME, "password": PASSWORD, "remember": 1}
|
||||||
|
logging.info("Login in as %s", data)
|
||||||
|
r = requests.post(AJAX_LOGIN, data=data)
|
||||||
|
resp = r.json()
|
||||||
|
if resp.get('status') == 1:
|
||||||
|
logging.info("Login success! %s", r.cookies)
|
||||||
|
self.__save_cookies(r.cookies)
|
||||||
|
else:
|
||||||
|
logging.error("Login failed! %s", resp)
|
||||||
|
sys.exit(1)
|
||||||
|
r.close()
|
||||||
|
|
||||||
|
def __get_share_page(self):
|
||||||
|
rid = self.id
|
||||||
|
|
||||||
|
res = session.post(SHARE_URL, data={"rid": rid}, cookies=self.__load_cookies()).json()
|
||||||
|
share_code = res['data'].split('/')[-1]
|
||||||
|
share_url = SHARE_WEB.format(code=share_code)
|
||||||
|
logging.info("Share url is %s", share_url)
|
||||||
|
|
||||||
|
# get api response
|
||||||
|
api_response = session.get(SHARE_API.format(code=share_code)).json()
|
||||||
|
return share_url, api_response
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
y = YYeTs()
|
||||||
@@ -1,112 +1,71 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
# YYeTsBot - utils.py
|
# YYeTsBot - utils.py
|
||||||
# 2019/8/15 20:27
|
# 2019/8/15 20:27
|
||||||
|
|
||||||
__author__ = 'Benny <benny.think@gmail.com>'
|
__author__ = 'Benny <benny.think@gmail.com>'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import pickle
|
import pickle
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import redis
|
import redis
|
||||||
|
|
||||||
from config import AJAX_LOGIN, USERNAME, PASSWORD, REDIS
|
from config import AJAX_LOGIN, USERNAME, PASSWORD, REDIS
|
||||||
|
|
||||||
r = redis.StrictRedis(host=REDIS, decode_responses=True)
|
r = redis.StrictRedis(host=REDIS, decode_responses=True)
|
||||||
|
|
||||||
cookie_file = os.path.join(os.path.dirname(__file__), 'data', 'cookies.dump')
|
cookie_file = os.path.join(os.path.dirname(__file__), 'data', 'cookies.dump')
|
||||||
|
|
||||||
|
|
||||||
def save_to_cache(url: str, value: dict) -> None:
|
|
||||||
data = json.dumps(value, ensure_ascii=False)
|
|
||||||
r.set(url, data, ex=3600 * 12)
|
def save_error_dump(uid, err: str):
|
||||||
|
r.set(uid, err)
|
||||||
|
|
||||||
def yyets_get_from_cache(url: str) -> dict:
|
|
||||||
logging.info("Reading data from cache %s", url)
|
def get_error_dump(uid) -> str:
|
||||||
from html_request import get_detail_page
|
err = r.get(uid)
|
||||||
|
r.delete(uid)
|
||||||
data = r.get(url)
|
if not err:
|
||||||
if data:
|
err = ""
|
||||||
logging.info("Cache hit")
|
return err
|
||||||
return json.loads(data)
|
|
||||||
else:
|
|
||||||
logging.info("Cache miss")
|
def redis_announcement(content="", op="get"):
|
||||||
save_to_cache(url, get_detail_page(url))
|
if op == "get":
|
||||||
return yyets_get_from_cache(url)
|
return r.get("announcement")
|
||||||
|
elif op == "set":
|
||||||
|
r.set("announcement", content)
|
||||||
def save_error_dump(uid, err: str):
|
elif op == "del":
|
||||||
r.set(uid, err)
|
r.delete("announcement")
|
||||||
|
|
||||||
|
|
||||||
def get_error_dump(uid) -> str:
|
def today_request(request_type: str):
|
||||||
err = r.get(uid)
|
if r.exists("usage"):
|
||||||
r.delete(uid)
|
data: str = r.get("usage")
|
||||||
if not err:
|
dict_data: dict = json.loads(data)
|
||||||
err = ""
|
dict_data[request_type] += 1
|
||||||
return err
|
saved_data: str = json.dumps(dict_data)
|
||||||
|
else:
|
||||||
|
data_format: dict = dict(total=0, invalid=0, answer=0, success=0, fail=0)
|
||||||
def redis_announcement(content="", op="get"):
|
data_format[request_type] += 1
|
||||||
if op == "get":
|
saved_data: str = json.dumps(data_format)
|
||||||
return r.get("announcement")
|
|
||||||
elif op == "set":
|
r.set("usage", saved_data)
|
||||||
r.set("announcement", content)
|
|
||||||
elif op == "del":
|
|
||||||
r.delete("announcement")
|
def reset_request():
|
||||||
|
r.delete("usage")
|
||||||
|
|
||||||
def save_cookies(requests_cookiejar):
|
|
||||||
with open(cookie_file, 'wb') as f:
|
def show_usage():
|
||||||
pickle.dump(requests_cookiejar, f)
|
m = "今天我已经服务了{total}次🤓,无效请求{invalid}😆,主人回复{answer}次🤨,成功请求{success}次😝,失败请求{fail}次🤣"
|
||||||
|
data: str = r.get("usage")
|
||||||
|
if r.exists("usage"):
|
||||||
def load_cookies():
|
dict_data: dict = json.loads(data)
|
||||||
with open(cookie_file, 'rb') as f:
|
else:
|
||||||
return pickle.load(f)
|
dict_data: dict = dict(total=0, invalid=0, answer=0, success=0, fail=0)
|
||||||
|
|
||||||
|
return m.format(**dict_data)
|
||||||
def login():
|
|
||||||
data = {"account": USERNAME, "password": PASSWORD, "remember": 1}
|
|
||||||
logging.info("Login in as %s", data)
|
|
||||||
r = requests.post(AJAX_LOGIN, data=data)
|
|
||||||
resp = r.json()
|
|
||||||
if resp.get('status') == 1:
|
|
||||||
logging.info("Login success! %s", r.cookies)
|
|
||||||
save_cookies(r.cookies)
|
|
||||||
else:
|
|
||||||
logging.error("Login failed! %s", resp)
|
|
||||||
sys.exit(1)
|
|
||||||
r.close()
|
|
||||||
|
|
||||||
|
|
||||||
def today_request(request_type: str):
|
|
||||||
if r.exists("usage"):
|
|
||||||
data: str = r.get("usage")
|
|
||||||
dict_data: dict = json.loads(data)
|
|
||||||
dict_data[request_type] += 1
|
|
||||||
saved_data: str = json.dumps(dict_data)
|
|
||||||
else:
|
|
||||||
data_format: dict = dict(total=0, invalid=0, answer=0, success=0, fail=0)
|
|
||||||
data_format[request_type] += 1
|
|
||||||
saved_data: str = json.dumps(data_format)
|
|
||||||
|
|
||||||
r.set("usage", saved_data)
|
|
||||||
|
|
||||||
|
|
||||||
def reset_request():
|
|
||||||
r.delete("usage")
|
|
||||||
|
|
||||||
|
|
||||||
def show_usage():
|
|
||||||
m = "今天我已经服务了{total}次🤓,无效请求{invalid}😆,主人回复{answer}次🤨,成功请求{success}次😝,失败请求{fail}次🤣"
|
|
||||||
data: str = r.get("usage")
|
|
||||||
if r.exists("usage"):
|
|
||||||
dict_data: dict = json.loads(data)
|
|
||||||
else:
|
|
||||||
dict_data: dict = dict(total=0, invalid=0, answer=0, success=0, fail=0)
|
|
||||||
|
|
||||||
return m.format(**dict_data)
|
|
||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Reference in New Issue
Block a user