mirror of
https://github.com/xingsu1021/pthelper.git
synced 2026-11-01 21:24:38 +08:00
新增rss功能
This commit is contained in:
@@ -30,6 +30,15 @@ pip install --no-cache-dir -r requirements.txt -i https://pypi.mirrors.ustc.edu.
|
||||
```
|
||||

|
||||
|
||||
# v2.2.0 说明
|
||||
|
||||
```shell
|
||||
1、新增RSS订阅功能。
|
||||
2、新增RSS订阅后直接发送TR下载,(QB未测试但已集成)。
|
||||
3、此版本不支持在线升级使用。
|
||||
```
|
||||

|
||||
|
||||
# v2.1.0 说明
|
||||
|
||||
```shell
|
||||
|
||||
@@ -1170,7 +1170,7 @@ def opencd(site_name, site_name_cn, site_url, site_cookie):
|
||||
logger.info(data_ocr)
|
||||
|
||||
#验证码不足6未跳过
|
||||
if len(data_ocr) < 6 :
|
||||
if len(data_ocr) != 6 :
|
||||
continue
|
||||
|
||||
data = {'imagehash': imagehash,
|
||||
@@ -1246,7 +1246,7 @@ def hdsky(site_name, site_name_cn, site_url, site_cookie):
|
||||
)
|
||||
try:
|
||||
|
||||
session = requests.session()
|
||||
#session = requests.session()
|
||||
|
||||
#验证码签到执行3次验证
|
||||
for i in range(3):
|
||||
@@ -1256,7 +1256,7 @@ def hdsky(site_name, site_name_cn, site_url, site_cookie):
|
||||
#print('i--------->',i)
|
||||
return False, "%s(%s) 错误:连续3次验证码失败" % (site_name,site_name_cn)
|
||||
|
||||
response = session.post(sign_url, headers=headers, data=data, timeout=10)
|
||||
response = requests.post(sign_url, headers=headers, data=data, timeout=10)
|
||||
logger.info(response.text)
|
||||
if response.status_code == 200:
|
||||
result = json.loads(response.text)
|
||||
@@ -1264,7 +1264,7 @@ def hdsky(site_name, site_name_cn, site_url, site_cookie):
|
||||
code = result['code']
|
||||
#拼接验证码图片
|
||||
hdsky_image_url = 'https://hdsky.me/image.php?action=regimage&imagehash=' + code
|
||||
response = session.get(hdsky_image_url, headers=headers, timeout=10)
|
||||
response = requests.get(hdsky_image_url, headers=headers, timeout=10)
|
||||
with open(image_code_name, "wb") as fp:
|
||||
fp.write(response.content)
|
||||
|
||||
@@ -1277,14 +1277,14 @@ def hdsky(site_name, site_name_cn, site_url, site_cookie):
|
||||
logger.info(data_ocr)
|
||||
|
||||
#验证码不足6未跳过
|
||||
if len(data_ocr) < 6 :
|
||||
if len(data_ocr) != 6 :
|
||||
continue
|
||||
|
||||
data = {'action': 'showup',
|
||||
'imagehash': code,
|
||||
'imagestring': data_ocr
|
||||
}
|
||||
response = session.post("https://hdsky.me/showup.php", headers=headers, data=data, timeout=10)
|
||||
response = requests.post("https://hdsky.me/showup.php", headers=headers, data=data, timeout=10)
|
||||
logger.info(response.text)
|
||||
try:
|
||||
result = json.loads(response.text)
|
||||
|
||||
@@ -121,8 +121,6 @@ def timesince(dt, since='', default="just now"):
|
||||
|
||||
_STRPTIME_LOCK = threading.Lock()
|
||||
|
||||
_GMT_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
|
||||
_ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%S.000Z"
|
||||
|
||||
def now_date():
|
||||
"""当前时间"""
|
||||
@@ -155,6 +153,7 @@ def http_to_unixtime(time_string):
|
||||
|
||||
HTTP Date形如 `Sat, 05 Dec 2015 11:10:29 GMT` 。
|
||||
"""
|
||||
_GMT_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
|
||||
return to_unixtime(time_string, _GMT_FORMAT)
|
||||
|
||||
def cst_to_unixtime(time_string):
|
||||
@@ -166,6 +165,7 @@ def cst_to_unixtime(time_string):
|
||||
|
||||
def iso8601_to_unixtime(time_string):
|
||||
"""把ISO8601时间字符串(形如,2012-02-24T06:07:48.000Z)转换为UNIX时间,精确到秒。"""
|
||||
_ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%S.000Z"
|
||||
return to_unixtime(time_string, _ISO8601_FORMAT)
|
||||
|
||||
def str2datetime(st, s_format='%Y-%m-%d %H:%M:%S'):
|
||||
@@ -249,10 +249,7 @@ def capacity_convert(size, expect='auto', rate=1000):
|
||||
return expect_size, expect
|
||||
|
||||
def filesizeformat(value, baseMB=False):
|
||||
"""Format the value like a 'human-readable' file size (i.e. 13 KB,
|
||||
4.1 MB, 102 bytes, etc). Per default decimal prefixes are used (mega,
|
||||
giga etc.), if the second parameter is set to `True` the binary
|
||||
prefixes are (mebi, gibi).
|
||||
"""将字节转换为 1.00KB 1.00Mb 1.00gb
|
||||
"""
|
||||
try:
|
||||
bytes = float(value)
|
||||
@@ -271,16 +268,16 @@ def filesizeformat(value, baseMB=False):
|
||||
if bytes < base:
|
||||
ret = '%d Bytes' % (bytes)
|
||||
elif bytes < base * base:
|
||||
ret = '%d KB' % (bytes / base)
|
||||
ret = '%.2f KB' % (bytes / base)
|
||||
elif bytes < base * base * base:
|
||||
ret = '%d MB' % (bytes / (base * base))
|
||||
ret = '%.2f MB' % (bytes / (base * base))
|
||||
elif bytes < base * base * base * base:
|
||||
if bytes % (base * base * base) == 0:
|
||||
ret = '%d GB' % (bytes / (base * base * base))
|
||||
if bytes % (base * base * base) >= 0:
|
||||
ret = '%.2f GB' % (bytes / (base * base * base))
|
||||
else:
|
||||
ret = "%d MB" % (bytes / (base * base))
|
||||
ret = "%.2f MB" % (bytes / (base * base))
|
||||
else:
|
||||
ret = '%.1f TB' % (bytes / (base * base * base * base))
|
||||
ret = '%.2f TB' % (bytes / (base * base * base * base))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@@ -6,12 +6,18 @@ from urllib import parse
|
||||
import os
|
||||
import logging
|
||||
from bs4 import BeautifulSoup
|
||||
import feedparser
|
||||
from thefuzz import process
|
||||
from transmission_rpc import Client
|
||||
import qbittorrentapi
|
||||
|
||||
from common.utils import send_email,send_telegram,send_iyuu, send_enwechat
|
||||
from common.utils import send_email,send_telegram,send_iyuu, send_enwechat, parseUrl
|
||||
from common.sites_sign import signIngress
|
||||
from sites.models import SiteConfig, SiteInfo
|
||||
from .models import Job, Log
|
||||
from notify.models import NotifyConfig
|
||||
from rss.models import Rule, SeedInfo
|
||||
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
|
||||
from django_apscheduler.jobstores import DjangoJobStore, register_job
|
||||
@@ -96,6 +102,9 @@ def my_scheduler(crontab_id=None, crontab_status=None, hour="*", minute="*", job
|
||||
elif jobtype_id == 1003:
|
||||
#重签
|
||||
scheduler.add_job(re_fail_sign, 'cron', hour=hour, minute=minute, id=crontab_id, args=[crontab_id])
|
||||
elif jobtype_id == 1002:
|
||||
#RSS订阅
|
||||
scheduler.add_job(rss, 'cron', hour=hour, minute=minute, id=crontab_id, args=[crontab_id])
|
||||
|
||||
else:
|
||||
#禁用状态,直接删除任务
|
||||
@@ -117,6 +126,8 @@ def my_scheduler(crontab_id=None, crontab_status=None, hour="*", minute="*", job
|
||||
scheduler.add_job(sign, 'cron', hour=hour, minute=minute, id=crontab_id, args=[crontab_id])
|
||||
elif jobtype_id == 1003:
|
||||
scheduler.add_job(re_fail_sign, 'cron', hour=hour, minute=minute, id=crontab_id, args=[crontab_id])
|
||||
elif jobtype_id == 1002:
|
||||
scheduler.add_job(rss, 'cron', hour=hour, minute=minute, id=crontab_id, args=[crontab_id])
|
||||
|
||||
|
||||
return True
|
||||
@@ -338,4 +349,224 @@ def send_msg(crontab_id = None, send_data = []):
|
||||
logger.info("-------------enwechat-------------------")
|
||||
logger.info(msg)
|
||||
|
||||
return
|
||||
|
||||
#==========================================================================================================
|
||||
def rss(crontab_id):
|
||||
"""
|
||||
执行订阅
|
||||
参数:
|
||||
crontab_id:执行任务的ID
|
||||
"""
|
||||
|
||||
headers = {
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
|
||||
#'cookie': site_cookie,
|
||||
}
|
||||
|
||||
#获取任务ID
|
||||
job_id = Job.objects.get(crontab_id=crontab_id)
|
||||
ormdata_rule = Rule.objects.get(job_id = job_id.id)
|
||||
#订阅地址
|
||||
rss_url = ormdata_rule.config_id.url
|
||||
#站点信息
|
||||
siteinfo_id = ormdata_rule.config_id.siteinfo_id
|
||||
site_name = siteinfo_id.siteconfig_name
|
||||
site_name_cn = siteinfo_id.siteconfig_name_cn
|
||||
#关键字
|
||||
keyword = [x for x in ormdata_rule.keyword.split(',')]
|
||||
#码率
|
||||
rate = ormdata_rule.rate
|
||||
|
||||
logger.info("-------------开始RSS订阅任务%s(%s)-------------------" % (site_name, site_name_cn))
|
||||
|
||||
d = feedparser.parse(rss_url, request_headers=headers)
|
||||
#未获取返回状态
|
||||
if 'status' not in d:
|
||||
logger.error('请求RSS地址失败')
|
||||
return
|
||||
|
||||
#匹配RSS过滤后发送
|
||||
send_data = []
|
||||
if d.status == 200:
|
||||
#entries 电影内容
|
||||
for i in d.entries:
|
||||
#标题 [Movie][Back to 1942 2012 V2 2160p WEB-DL H265 AAC-LeagueWEB][一九四二/温故1942/1942 | 类型: 剧情/历史/战争/灾难 主演: 张国立/张默/徐帆 [国语/中英双语硬字] | *4K* *V2高码*][16.35 GB]
|
||||
seed_name = i.title
|
||||
#种子类型 Movie
|
||||
seed_type = i.tags[0].term
|
||||
#种子页地址 https://lemonhd.org/details_movie.php?id=327311
|
||||
seed_link = i.link
|
||||
#'links': [{'rel': 'alternate', 'type': 'text/html', 'href': 'https://lemonhd.org/details_tv.php?id=328435'},
|
||||
# {'length': '2543569030', 'type': 'application/x-bittorrent', 'href': 'https://lemonhd.org/download.php?id=328435&passkey=c1c6b3d5291bf330ffa9ad2872d52144',
|
||||
# 'rel': 'enclosure'}
|
||||
# ]
|
||||
#种子下载地址
|
||||
seed_download_url = i.links[1].href
|
||||
#种子大小 字节数
|
||||
seed_length = i.links[1].length
|
||||
#发布时间 Wed, 07 Sep 2022 14:27:09 +0800
|
||||
seed_published_time = i.published
|
||||
_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S %z"
|
||||
#将字符串转换成datetime在格式化成需要的 2022-09-07 09:26:22
|
||||
seed_published_time = datetime.datetime.strptime(seed_published_time, _TIME_FORMAT).strftime('%Y-%m-%d %H:%M:%S')
|
||||
#种子ID afe783da83684e92f5ff6a4c42fd11da216b77a2
|
||||
seed_hash_id = i.id
|
||||
|
||||
seedinfo = None
|
||||
#确认无重复,则添加
|
||||
num = SeedInfo.objects.filter(seed_hash_id=seed_hash_id).filter(siteinfo_id=siteinfo_id).count()
|
||||
if num == 0:
|
||||
if keyword[0] == '':
|
||||
|
||||
#未添加关键字则全部加入
|
||||
if rate == 'all':
|
||||
#码率为所有
|
||||
seedinfo = SeedInfo.objects.create(seed_name = seed_name,
|
||||
seed_type = seed_type,
|
||||
seed_details_link = seed_link,
|
||||
seed_donwload_link = seed_download_url,
|
||||
seed_file_size = seed_length,
|
||||
seed_hash_id = seed_hash_id,
|
||||
seed_published_time = seed_published_time,
|
||||
siteinfo_id = siteinfo_id,
|
||||
rule_id = ormdata_rule
|
||||
)
|
||||
else:
|
||||
if rate in seed_name:
|
||||
seedinfo = SeedInfo.objects.create(seed_name = seed_name,
|
||||
seed_type = seed_type,
|
||||
seed_details_link = seed_link,
|
||||
seed_donwload_link = seed_download_url,
|
||||
seed_file_size = seed_length,
|
||||
seed_hash_id = seed_hash_id,
|
||||
seed_published_time = seed_published_time,
|
||||
siteinfo_id = siteinfo_id,
|
||||
rule_id = ormdata_rule
|
||||
)
|
||||
#发送下载器
|
||||
seed_download(seedinfo.id)
|
||||
#将电影名加入发送
|
||||
send_data.append(seed_name)
|
||||
else:
|
||||
#通过匹配关键字添加
|
||||
_name, num=process.extractOne(seed_name, keyword)
|
||||
if num >= 50:
|
||||
#匹配度大于50添加
|
||||
if rate == 'all':
|
||||
#码率为所有
|
||||
seedinfo = SeedInfo.objects.create(seed_name = seed_name,
|
||||
seed_type = seed_type,
|
||||
seed_details_link = seed_link,
|
||||
seed_donwload_link = seed_download_url,
|
||||
seed_file_size = seed_length,
|
||||
seed_hash_id = seed_hash_id,
|
||||
seed_published_time = seed_published_time,
|
||||
siteinfo_id = siteinfo_id,
|
||||
rule_id = ormdata_rule
|
||||
)
|
||||
else:
|
||||
if rate in seed_name:
|
||||
seedinfo = SeedInfo.objects.create(seed_name = seed_name,
|
||||
seed_type = seed_type,
|
||||
seed_details_link = seed_link,
|
||||
seed_donwload_link = seed_download_url,
|
||||
seed_file_size = seed_length,
|
||||
seed_hash_id = seed_hash_id,
|
||||
seed_published_time = seed_published_time,
|
||||
siteinfo_id = siteinfo_id,
|
||||
rule_id = ormdata_rule
|
||||
)
|
||||
#发送下载器
|
||||
seed_download(seedinfo.id)
|
||||
#将电影名加入发送
|
||||
send_data.append(seed_name)
|
||||
#发送通知
|
||||
send_msg(crontab_id,send_data)
|
||||
|
||||
return
|
||||
|
||||
def seed_download(seedinfo_id):
|
||||
"""
|
||||
下载种子
|
||||
参数
|
||||
seedinfo_id rss订阅后存入数据库的id
|
||||
"""
|
||||
|
||||
ormdata_seedinfo = SeedInfo.objects.get(id = seedinfo_id)
|
||||
#下载连接
|
||||
seed_donwload_link = ormdata_seedinfo.seed_donwload_link
|
||||
#下载器类型
|
||||
download_type = ormdata_seedinfo.rule_id.tools_id.typed
|
||||
download_username = ormdata_seedinfo.rule_id.tools_id.username
|
||||
download_password = ormdata_seedinfo.rule_id.tools_id.password
|
||||
download_url = ormdata_seedinfo.rule_id.tools_id.url
|
||||
#下载目录
|
||||
download_dirname = ormdata_seedinfo.rule_id.tools_id.dirname
|
||||
#加入下载器后是否立刻下载
|
||||
is_paused = ormdata_seedinfo.rule_id.is_paused
|
||||
|
||||
if download_dirname == "":
|
||||
download_dirname = None
|
||||
|
||||
url_data = parseUrl(download_url)
|
||||
|
||||
#保存加入下载器后返回的ID
|
||||
torrent_id = None
|
||||
if download_type == 'tr':
|
||||
try:
|
||||
|
||||
c = Client(protocol= url_data['protocol'],
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=download_username,
|
||||
password=download_password,
|
||||
timeout = 10
|
||||
)
|
||||
|
||||
torrent = c.add_torrent(seed_donwload_link,
|
||||
timeout = 10,
|
||||
download_dir = download_dirname,
|
||||
#paused = is_paused, #立刻下载,需要下载器开启默认下载才有效
|
||||
)
|
||||
#获取种子id
|
||||
torrent_id = torrent.id
|
||||
#如果启动则下载
|
||||
if is_paused:
|
||||
c.start_torrent(torrent_id)
|
||||
|
||||
ormdata_seedinfo.seed_torrent_id = torrent_id
|
||||
ormdata_seedinfo.seed_status = True
|
||||
ormdata_seedinfo.save()
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
elif download_type == 'qb':
|
||||
try:
|
||||
|
||||
c = qbittorrentapi.Client(
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=download_username,
|
||||
password=download_password,
|
||||
)
|
||||
|
||||
torrent = c.torrents_add(seed_donwload_link,
|
||||
save_path=download_dirname,
|
||||
#is_paused=is_paused, #立刻下载
|
||||
)
|
||||
#获取种子id
|
||||
torrent_id = torrent.id
|
||||
#如果启动则下载
|
||||
if is_paused:
|
||||
c.start_torrent(torrent_id)
|
||||
|
||||
ormdata_seedinfo.seed_torrent_id = torrent_id
|
||||
ormdata_seedinfo.seed_status = True
|
||||
ormdata_seedinfo.save()
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
return
|
||||
@@ -545,14 +545,14 @@ class SignJobView(LoginRequiredMixin,TemplateView):
|
||||
name = "签到"
|
||||
|
||||
#未配置消息通知不予通过
|
||||
if len(notifys) == 0:
|
||||
response_data={"code":0,"msg":"请配置消息通知!"}
|
||||
return JsonResponse(response_data)
|
||||
#if len(notifys) == 0:
|
||||
#response_data={"code":0,"msg":"请配置消息通知!"}
|
||||
#return JsonResponse(response_data)
|
||||
|
||||
data_count = Job.objects.filter(jobtype_id=1000).count()
|
||||
if data_count == 0:
|
||||
ormdata = Job.objects.create(name=name,
|
||||
crontab_status=crontab_status,
|
||||
crontab_status=int(crontab_status),
|
||||
hour=hour,
|
||||
minute=minute,
|
||||
jobtype_id=jobtype_id,
|
||||
@@ -563,7 +563,7 @@ class SignJobView(LoginRequiredMixin,TemplateView):
|
||||
)
|
||||
else:
|
||||
ormdata = Job.objects.get(id=_id)
|
||||
ormdata.crontab_status = crontab_status
|
||||
ormdata.crontab_status = int(crontab_status)
|
||||
ormdata.hour = hour
|
||||
ormdata.minute = minute
|
||||
ormdata.crontab_time = crontab_time
|
||||
|
||||
0
apps/download/__init__.py
Normal file
0
apps/download/__init__.py
Normal file
3
apps/download/admin.py
Normal file
3
apps/download/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
apps/download/apps.py
Normal file
6
apps/download/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class DownloadConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'download'
|
||||
26
apps/download/migrations/0001_initial.py
Normal file
26
apps/download/migrations/0001_initial.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 4.1 on 2022-09-08 14:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Tools',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=30, verbose_name='下载器名称')),
|
||||
('typed', models.CharField(max_length=30, verbose_name='下载器类型tr,qb')),
|
||||
('url', models.URLField(blank=True, verbose_name='下载器地址')),
|
||||
('username', models.CharField(max_length=50, verbose_name='下载器用户名')),
|
||||
('password', models.CharField(max_length=128, verbose_name='下载器密码')),
|
||||
('dirname', models.CharField(max_length=150, null=True, verbose_name='默认下载目录')),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
apps/download/migrations/0002_alter_tools_name.py
Normal file
18
apps/download/migrations/0002_alter_tools_name.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.1 on 2022-09-08 17:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('download', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tools',
|
||||
name='name',
|
||||
field=models.CharField(max_length=30, unique=True, verbose_name='下载器名称'),
|
||||
),
|
||||
]
|
||||
0
apps/download/migrations/__init__.py
Normal file
0
apps/download/migrations/__init__.py
Normal file
12
apps/download/models.py
Normal file
12
apps/download/models.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class Tools(models.Model):
|
||||
"""下载器"""
|
||||
name = models.CharField('下载器名称', max_length=30, unique=True)
|
||||
typed = models.CharField('下载器类型tr,qb', max_length=30)
|
||||
url = models.URLField('下载器地址', blank=True)
|
||||
username = models.CharField('下载器用户名', max_length=50)
|
||||
password = models.CharField('下载器密码', max_length=128)
|
||||
dirname = models.CharField('默认下载目录', max_length=150, null=True)
|
||||
235
apps/download/templates/download/tools.html
Normal file
235
apps/download/templates/download/tools.html
Normal file
@@ -0,0 +1,235 @@
|
||||
|
||||
<style>
|
||||
#toolsTable + .layui-table-view .layui-table-body tbody > tr > td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#toolsTable + .layui-table-view .layui-table-body tbody > tr > td > .layui-table-cell {
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.tb-img-circle {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
cursor: zoom-in;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #dddddd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 正文开始 -->
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
|
||||
<div class="layui-form toolbar">
|
||||
<div class="layui-form-item">
|
||||
|
||||
<div class="layui-inline searchInput">
|
||||
<input id="toolsSearchValue" class="layui-input" type="text" placeholder="输入关键字" />
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button id="toolsBtnSearch" class="layui-btn icon-btn"><i class="layui-icon"></i>搜索
|
||||
</button>
|
||||
<button id="toolsBtnAdd" class="layui-btn icon-btn"><i
|
||||
class="layui-icon"></i>添加</button>
|
||||
<button id="toolsBtnDel" class="layui-btn layui-btn-danger icon-btn"><i
|
||||
class="layui-icon"></i>删除</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="layui-table" id="toolsTable" lay-filter="toolsTable"></table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 表格操作列 -->
|
||||
<script type="text/html" id="toolsTableBar">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'xmSelect', 'formX', 'dropdown', 'upload'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var upload = layui.upload;
|
||||
|
||||
form.render('select');
|
||||
// 渲染表格
|
||||
var insTb = tableX.render({
|
||||
elem: '#toolsTable',
|
||||
url: setter.base_server + 'download/tools/list',
|
||||
method: 'GET',
|
||||
cellMinWidth: 100,
|
||||
page: true,
|
||||
limit: 15,
|
||||
limits: [15, 50, 100],
|
||||
cols: [[
|
||||
{ type: 'checkbox' },
|
||||
{ field: 'id', title: 'ID', hide: true },
|
||||
{ field: 'name', sort: true, title: '名称', width: 200 },
|
||||
{ field: 'typed', title: '类型', templet: function (d) {
|
||||
if (d.typed === 'tr') {
|
||||
return '<img src="static/assets/images/tr.png" class="tb-img-circle" tb-img alt=""/>';
|
||||
}else{
|
||||
return '<img src="static/assets/images/qb.png" class="tb-img-circle" tb-img alt=""/>';
|
||||
}
|
||||
}, align: 'center', width: 90, unresize: true
|
||||
},
|
||||
{ field: 'url', sort: true, title: '地址' },
|
||||
{ field: 'username', sort: true, title: '用户名', width: 150 },
|
||||
{ field: 'password', sort: true, title: '密码' , hide: true},
|
||||
{ field: 'dirname', sort: true, title: '下载目录' },
|
||||
{ align: 'center', toolbar: '#toolsTableBar', title: '操作', width: 150 }
|
||||
]]
|
||||
});
|
||||
|
||||
|
||||
// 添加按钮点击事件
|
||||
$('#toolsBtnAdd').click(function () {
|
||||
showAddModel();
|
||||
});
|
||||
|
||||
// 工具条点击事件
|
||||
table.on('tool(toolsTable)', function (obj) {
|
||||
var data = obj.data;
|
||||
var layEvent = obj.event;
|
||||
|
||||
if (layEvent === 'edit') { // 修改
|
||||
showEditModel(data);
|
||||
} else if (layEvent === 'del') {
|
||||
|
||||
//var csrftoken = getCookie('csrftoken');
|
||||
layer.confirm('确定删除此记录 ' + data.name + '?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
$.ajax({
|
||||
url: "download/tools/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': [data.id], csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
// beforeSend: function(request) {
|
||||
// //django需要csrf验证,Forbidden (CSRF cookie not set.):
|
||||
// request.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
// },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('toolsTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//显示表单弹窗
|
||||
var showAddModel = function () {
|
||||
var title = '添加下载器';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '500px'],
|
||||
url: 'download/tools/add',
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var showEditModel = function (data) {
|
||||
var title = '编辑下载器';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '500px'],
|
||||
url: 'download/tools/edit?id=' + data.id,
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 批量删除按钮点击事件
|
||||
$('#toolsBtnDel').click(function () {
|
||||
//选中事件
|
||||
var checkStatus = table.checkStatus('toolsTable')
|
||||
//得到选择长度
|
||||
dataLength = checkStatus.data.length
|
||||
data = checkStatus.data;
|
||||
var ids = [];
|
||||
if (dataLength == 0) {
|
||||
//未选中
|
||||
layer.msg("请选择需要删除的记录", { icon: 2 });
|
||||
} else {
|
||||
layer.confirm('确定删除选中的' + dataLength + '个记录?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ids.push(data[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: "download/tools/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': ids, csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('toolsTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听enter键,光标在搜索框
|
||||
$('#toolsSearchValue').keydown(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
var key = 'search';
|
||||
var value = $('#toolsSearchValue').val();
|
||||
|
||||
table.reload('toolsTable', { where: { searchKey: key, searchValue: value } });
|
||||
} else if (event.keyCode === 8 && !$psw.val()) {
|
||||
$("#toolsSearchValue").val('');
|
||||
ptable();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
if (event.returnValue) event.returnValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索按钮点击事件
|
||||
$('#toolsBtnSearch').click(function () {
|
||||
var key = 'search';
|
||||
var value = $('#toolsSearchValue').val();
|
||||
|
||||
table.reload('toolsTable', { where: { searchKey: key, searchValue: value } });
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
112
apps/download/templates/download/toolsadd.html
Normal file
112
apps/download/templates/download/toolsadd.html
Normal file
@@ -0,0 +1,112 @@
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="toolsAddForm" lay-filter="toolsAddForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="name" type="text" class="layui-input" lay-verify="required" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="typed"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="url" type="text" class="layui-input" lay-verify="required|urlX" required placeholder="如:http://1.1.1.1:9091" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="username" type="text" class="layui-input" lay-verify="required" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="password" type="password" class="layui-input" lay-verify="required" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">下载目录</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="dirname" type="text" class="layui-input" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-normal" lay-filter="toolsTestForm-submit" lay-submit>测试连接</button>        
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="toolsAddForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'formX', 'dropdown'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
|
||||
|
||||
form.render('select', 'toolsAddForm');
|
||||
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#typed',
|
||||
name: 'typed',
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
data: [
|
||||
{name: 'Transmission', value: 'tr'},
|
||||
{name: 'qBittorrent', value: 'qb'},
|
||||
]
|
||||
});
|
||||
|
||||
form.on('submit(toolsTestForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('download/tools/test', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, 'POST');
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
form.on('submit(toolsAddForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('download/tools/add', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('toolsTable', {});
|
||||
admin.closeDialog('#toolsAddForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#toolsAddForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
140
apps/download/templates/download/toolsedit.html
Normal file
140
apps/download/templates/download/toolsedit.html
Normal file
@@ -0,0 +1,140 @@
|
||||
<style type="text/css">
|
||||
#img {
|
||||
width: 25px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
margin-top: 12px;
|
||||
top: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="toolsEditForm" lay-filter="toolsEditForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
<input name="id" type="hidden" value="{{id}}"/>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="name" type="text" class="layui-input" lay-verify="required" required value="{{name}}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="typed"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="url" type="text" class="layui-input" lay-verify="required|urlX" required value="{{url}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户名</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="username" type="text" class="layui-input" lay-verify="required" required value="{{username}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="password" id="password" type="password" class="layui-input" lay-verify="required" required value="{{password}}" onfocus="this.placeholder=''"
|
||||
onblur="this.placeholder='密码'"/>
|
||||
<!--在输入框后接img标签-->
|
||||
<img id="img" onclick="hideShowPsw()" src="static/assets/images/icon-visible.png">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">下载目录</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="dirname" type="text" class="layui-input" value="{{dirname}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-normal" lay-filter="toolsTestForm-submit" lay-submit>测试连接</button>        
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="toolsEditForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'xmSelect', 'table', 'admin','formX'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var table = layui.table;
|
||||
var admin = layui.admin;
|
||||
|
||||
var formX = layui.formX;
|
||||
|
||||
form.render('select',"toolsEditForm");
|
||||
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#typed',
|
||||
name: 'typed',
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
data: [
|
||||
{name: 'Transmission', value: 'tr'},
|
||||
{name: 'qBittorrent', value: 'qb'},
|
||||
]
|
||||
});
|
||||
|
||||
insSel.setValue(["{{typed}}"]);
|
||||
|
||||
form.on('submit(toolsTestForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('download/tools/test', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, 'POST');
|
||||
return false;
|
||||
});
|
||||
|
||||
form.on('submit(toolsEditForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('download/tools/edit', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('toolsTable', {});
|
||||
admin.closeDialog('#toolsEditForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#toolsEditForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
//隐藏text block,显示password block
|
||||
var demoImg = document.getElementById("img");
|
||||
var PWD = document.getElementById("password");
|
||||
|
||||
function hideShowPsw() {
|
||||
if (PWD.type == "password") {
|
||||
PWD.type = "text";
|
||||
demoImg.src = "static/assets/images/icon-invisible.png"; //图片路径(闭眼图片)
|
||||
} else {
|
||||
PWD.type = "password";
|
||||
demoImg.src = "static/assets/images/icon-visible.png"; // 图片路径(睁眼图片)
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
3
apps/download/tests.py
Normal file
3
apps/download/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
1
apps/download/urls/__init__.py
Normal file
1
apps/download/urls/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
21
apps/download/urls/views_urls.py
Normal file
21
apps/download/urls/views_urls.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# coding:utf-8
|
||||
from django.urls import path
|
||||
from .. import views, views_request
|
||||
|
||||
app_name = 'download'
|
||||
|
||||
urlpatterns = [
|
||||
# Resource asset path
|
||||
|
||||
#下载器配置
|
||||
|
||||
path('tools', views.ToolsListView.as_view()),
|
||||
path('tools/add', views.ToolsAddView.as_view()),
|
||||
path('tools/edit', views.ToolsEditView.as_view()),
|
||||
path('tools/del', views.ToolsDelView.as_view()),
|
||||
path('tools/list', views_request.tools),
|
||||
path('tools/select/list', views_request.select_tools),
|
||||
path('tools/test', views_request.tools_test),
|
||||
|
||||
]
|
||||
|
||||
165
apps/download/views.py
Normal file
165
apps/download/views.py
Normal file
@@ -0,0 +1,165 @@
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import TemplateView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import JsonResponse
|
||||
|
||||
from .models import Tools
|
||||
|
||||
# Create your views here.
|
||||
|
||||
class ToolsListView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
显示
|
||||
"""
|
||||
template_name = 'download/tools.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
return super(ToolsListView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
# 'data': self.ormdata_game
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ToolsListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class ToolsAddView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
添加
|
||||
"""
|
||||
template_name = 'download/toolsadd.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
"""
|
||||
return super(ToolsAddView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ToolsAddView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
#数据提交接收方法
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
name = request.POST.get("name").strip()
|
||||
url = request.POST.get("url").strip()
|
||||
typed = request.POST.get("typed").strip()
|
||||
username = request.POST.get("username").strip()
|
||||
password = request.POST.get("password").strip()
|
||||
dirname = request.POST.get("dirname").strip()
|
||||
|
||||
|
||||
ormdata = Tools.objects.create(name=name,
|
||||
url=url,
|
||||
typed=typed,
|
||||
username=username,
|
||||
password=password,
|
||||
dirname=dirname
|
||||
)
|
||||
|
||||
ormdata.save()
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class ToolsEditView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
编辑域名
|
||||
"""
|
||||
template_name = 'download/toolsedit.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
得到
|
||||
"""
|
||||
|
||||
#记录ID
|
||||
self._id = request.GET.get('id')
|
||||
self.ormdata = Tools.objects.get(id=self._id)
|
||||
|
||||
return super(ToolsEditView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
'id': self._id,
|
||||
'url': self.ormdata.url,
|
||||
'name': self.ormdata.name,
|
||||
'typed': self.ormdata.typed,
|
||||
'username': self.ormdata.username,
|
||||
'password': self.ormdata.password,
|
||||
'dirname': self.ormdata.dirname
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(ToolsEditView, self).get_context_data(**kwargs)
|
||||
|
||||
#数据提交接收方法
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
url = request.POST.get("url").strip()
|
||||
name = request.POST.get("name").strip()
|
||||
typed = request.POST.get("typed").strip()
|
||||
username = request.POST.get("username").strip()
|
||||
password = request.POST.get("password").strip()
|
||||
dirname = request.POST.get("dirname").strip()
|
||||
|
||||
_id = request.POST.get('id')
|
||||
|
||||
ormdata = Tools.objects.get(id=_id)
|
||||
|
||||
ormdata.url = url
|
||||
ormdata.name=name
|
||||
ormdata.typed = typed
|
||||
ormdata.username = username
|
||||
ormdata.password = password
|
||||
ormdata.dirname = dirname
|
||||
|
||||
ormdata.save()
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class ToolsDelView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
删除
|
||||
"""
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
|
||||
#得到批量或者单个要删除的id
|
||||
ids = request.POST.getlist("ids[]")
|
||||
#print("ids====>",ids)
|
||||
|
||||
Tools.objects.filter(id__in=ids).delete()
|
||||
|
||||
#Site.objects.filter(id=i).delete()
|
||||
|
||||
response_data={"code":1,"msg":"操作成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
#==================
|
||||
158
apps/download/views_request.py
Normal file
158
apps/download/views_request.py
Normal file
@@ -0,0 +1,158 @@
|
||||
#coding=utf-8
|
||||
from django.http import JsonResponse, StreamingHttpResponse,HttpResponse
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from transmission_rpc import Client
|
||||
import qbittorrentapi
|
||||
|
||||
from .models import Tools
|
||||
from common.utils import parseUrl
|
||||
|
||||
#直接使用检查是否管理员
|
||||
#from django.contrib.auth.decorators import user_passes_test
|
||||
#@user_passes_test(lambda u: u.is_superuser)
|
||||
|
||||
@login_required
|
||||
def tools(request):
|
||||
"""
|
||||
提供相应的数据
|
||||
"""
|
||||
|
||||
#得到偏移量
|
||||
pageIndex= int(request.GET.get('page',1))
|
||||
#得到查询个数
|
||||
pageSize = int(request.GET.get('limit',10))
|
||||
|
||||
#搜索字段
|
||||
searchKey = request.GET.get('searchKey','')
|
||||
searchValue = request.GET.get('searchValue','')
|
||||
#去掉空格
|
||||
searchValue = searchValue.strip()
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
if searchValue == '':
|
||||
|
||||
data['count'] = Tools.objects.count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Tools.objects.order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Tools.objects.order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
else:
|
||||
|
||||
data['count'] = Tools.objects.filter(Q(name__icontains=searchValue)|Q(typed__icontains=searchValue)).count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Tools.objects.filter(Q(name__icontains=searchValue)|Q(typed__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Tools.objects.filter(Q(name__icontains=searchValue)|Q(typed__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({"id":i.id,
|
||||
"name":i.name,
|
||||
"typed":i.typed,
|
||||
"username":i.username,
|
||||
"url":i.url,
|
||||
"password":i.password,
|
||||
"dirname":i.dirname,
|
||||
})
|
||||
#返回json串
|
||||
#return HttpResponse(json.dumps(data,ensure_ascii = False), "application/json")
|
||||
return JsonResponse(data)
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def tools_test(request):
|
||||
"""
|
||||
测试下载器配置连通性
|
||||
"""
|
||||
|
||||
url = request.POST.get("url").strip()
|
||||
typed = request.POST.get("typed").strip()
|
||||
username = request.POST.get("username").strip()
|
||||
password = request.POST.get("password").strip()
|
||||
|
||||
url_data = parseUrl(url)
|
||||
|
||||
if typed == 'tr':
|
||||
try:
|
||||
|
||||
c = Client(protocol= url_data['protocol'],
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=username,
|
||||
password=password,
|
||||
timeout = 10
|
||||
)
|
||||
|
||||
response_data={"code":1,"msg": "连接成功" }
|
||||
except:
|
||||
response_data={"code":0,"msg": "连接失败" }
|
||||
elif typed == 'qb':
|
||||
|
||||
c = qbittorrentapi.Client(
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=username,
|
||||
password=password,
|
||||
)
|
||||
|
||||
try:
|
||||
c.auth_log_in()
|
||||
response_data={"code":1,"msg": "连接成功" }
|
||||
except:
|
||||
response_data={"code":0,"msg": "连接失败" }
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def select_tools(request):
|
||||
"""
|
||||
RSS规则
|
||||
xmSelect
|
||||
"""
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
#获取所有记录
|
||||
data['count'] = Tools.objects.count()
|
||||
|
||||
ormdata = Tools.objects.order_by(order_by).all()
|
||||
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({
|
||||
"id":i.id,
|
||||
"name":i.name
|
||||
})
|
||||
|
||||
return JsonResponse(data)
|
||||
@@ -1,16 +1,17 @@
|
||||
from myauth.models import User
|
||||
from django.contrib.auth.hashers import make_password
|
||||
|
||||
from sites.models import SiteConfig
|
||||
from sites.models import SiteConfig, SiteInfo
|
||||
from cron.models import JobType
|
||||
from notify.models import MailType
|
||||
from rss.models import FilmCategory, FilmType
|
||||
|
||||
def init_datas():
|
||||
"""
|
||||
初始化数据库
|
||||
"""
|
||||
print('开始初始化用户数据库...')
|
||||
|
||||
|
||||
if User.objects.count() == 0:
|
||||
#添加管理员
|
||||
User.objects.create(name='admin',
|
||||
@@ -24,7 +25,7 @@ def init_datas():
|
||||
print('初始化管理员成功.')
|
||||
else:
|
||||
print("管理员已经存在,忽略...")
|
||||
|
||||
|
||||
print('开始初始化站点配置...')
|
||||
sites_data = [{'name':'hdfans','name_cn':'红豆饭','index_url':'https://hdfans.org','sign_type':'general'},
|
||||
{'name':'1ptba','name_cn':'壹PT吧','index_url':'https://1ptba.com','sign_type':'general'},
|
||||
@@ -78,7 +79,7 @@ def init_datas():
|
||||
{'name':'wintersakura','name_cn':'冬樱','index_url':'https://wintersakura.net','sign_type':'general'},
|
||||
{'name':'hdpt','name_cn':'明教','index_url':'https://hdpt.xyz','sign_type':'general'},
|
||||
]
|
||||
|
||||
|
||||
for site in sites_data:
|
||||
get_site = SiteConfig.objects.filter(name=site['name']).count()
|
||||
if get_site == 0:
|
||||
@@ -91,18 +92,25 @@ def init_datas():
|
||||
#else:
|
||||
##更新站点配置
|
||||
#SiteConfig.objects.filter(name=site['name']).update(sign_type = site['sign_type'])
|
||||
|
||||
|
||||
#print('站点 [%s] 更新成功' % site['name'])
|
||||
##print('站点 [%s] 已经存在,忽略...' % site['name'])
|
||||
|
||||
|
||||
print('开始修复站点信息中文名称...')
|
||||
ormdata_siteinfo = SiteInfo.objects.filter(siteconfig_name_cn='')
|
||||
for siteinfo in ormdata_siteinfo:
|
||||
|
||||
siteconfig_name_cn = list(SiteConfig.objects.filter(name=siteinfo.siteconfig_name).values_list('name_cn',flat=True))
|
||||
SiteInfo.objects.filter(siteconfig_name=siteinfo.siteconfig_name).update(siteconfig_name_cn = siteconfig_name_cn[0])
|
||||
|
||||
|
||||
print('开始初始化任务类型...')
|
||||
jobtypes_data = [{'name':'签到','type_id':1000},
|
||||
{'name':'辅种','type_id':1001},
|
||||
{'name':'刷流','type_id':1002},
|
||||
{'name':'RSS订阅','type_id':1002},
|
||||
{'name':'签到重试','type_id':1003},
|
||||
]
|
||||
|
||||
|
||||
for jobtype in jobtypes_data:
|
||||
get_jobtype = JobType.objects.filter(name=jobtype['name']).count()
|
||||
if get_jobtype == 0:
|
||||
@@ -111,14 +119,16 @@ def init_datas():
|
||||
)
|
||||
print('添加任务类型 [%s] 成功' % jobtype['name'])
|
||||
else:
|
||||
#将原刷流更新为RSS订阅
|
||||
JobType.objects.filter(type_id=1002).update(name = 'RSS订阅')
|
||||
print('任务类型 [%s] 已经存在,忽略...' % jobtype['name'])
|
||||
|
||||
|
||||
print('开始初始化通知邮箱类型...')
|
||||
mailtypes_data = [{'name':'QQ邮箱','alias_name':'qq','smtp_server':'smtp.qq.com','smtp_port':465},
|
||||
{'name':'新浪邮箱(非vip)','alias_name':'sina','smtp_server':'smtp.sina.com','smtp_port':465},
|
||||
{'name':'网易163邮箱','alias_name':'163','smtp_server':'smtp.163.com','smtp_port':465},
|
||||
{'name':'新浪邮箱(非vip)','alias_name':'sina','smtp_server':'smtp.sina.com','smtp_port':465},
|
||||
{'name':'网易163邮箱','alias_name':'163','smtp_server':'smtp.163.com','smtp_port':465},
|
||||
]
|
||||
|
||||
|
||||
for mailtype in mailtypes_data:
|
||||
get_mailtype = MailType.objects.filter(name=mailtype['name']).count()
|
||||
if get_mailtype == 0:
|
||||
@@ -130,6 +140,62 @@ def init_datas():
|
||||
print('添加邮箱类型 [%s] 成功' % mailtype['name'])
|
||||
else:
|
||||
print('邮箱类型 [%s] 已经存在,忽略...' % mailtype['name'])
|
||||
|
||||
|
||||
filmcategorys_data = [{'name_en':'Movies','name_cn':'电影'},
|
||||
{'name_en':'TV Series','name_cn':'电视剧'},
|
||||
{'name_en':'Docs','name_cn':'纪录片'},
|
||||
{'name_en':'Animations','name_cn':'动画片'},
|
||||
{'name_en':'TV Shows','name_cn':'综艺'},
|
||||
{'name_en':'Sports','name_cn':'体育'},
|
||||
{'name_en':'MV','name_cn':'音乐视频'},
|
||||
{'name_en':'Music','name_cn':'音乐'},
|
||||
{'name_en':'Others','name_cn':'其他'},
|
||||
]
|
||||
for film_category in filmcategorys_data:
|
||||
get_film_category = FilmCategory.objects.filter(name_en=film_category['name_en']).count()
|
||||
if get_film_category == 0:
|
||||
FilmCategory.objects.create(name_en = film_category['name_en'],
|
||||
name_cn = film_category['name_cn']
|
||||
)
|
||||
print('添加影视类别 [%s] 成功' % film_category['name_en'])
|
||||
else:
|
||||
print('影视类别 [%s] 已经存在,忽略...' % film_category['name_en'])
|
||||
|
||||
filmtype_data = [{'name':'喜剧'},
|
||||
{'name':'爱情'},
|
||||
{'name':'动作'},
|
||||
{'name':'科幻'},
|
||||
{'name':'动画'},
|
||||
{'name':'悬疑'},
|
||||
{'name':'犯罪'},
|
||||
{'name':'惊悚'},
|
||||
{'name':'冒险'},
|
||||
{'name':'音乐'},
|
||||
{'name':'历史'},
|
||||
{'name':'奇幻'},
|
||||
{'name':'恐怖'},
|
||||
{'name':'战争'},
|
||||
{'name':'传记'},
|
||||
{'name':'歌舞'},
|
||||
{'name':'武侠'},
|
||||
{'name':'情色'},
|
||||
{'name':'灾难'},
|
||||
{'name':'西部'},
|
||||
{'name':'纪录片'},
|
||||
{'name':'短片'},
|
||||
{'name':'真人秀'},
|
||||
{'name':'脱口秀'},
|
||||
{'name':'古装'},
|
||||
{'name':'家庭'},
|
||||
{'name':'剧情'},
|
||||
]
|
||||
|
||||
for film_type in filmtype_data:
|
||||
get_film_type = FilmType.objects.filter(name=film_type['name']).count()
|
||||
if get_film_type == 0:
|
||||
FilmType.objects.create(name = film_type['name'])
|
||||
print('添加影视类型 [%s] 成功' % film_type['name'])
|
||||
else:
|
||||
print('影视类型 [%s] 已经存在,忽略...' % film_type['name'])
|
||||
|
||||
print('初始化成功.')
|
||||
|
||||
@@ -23,37 +23,37 @@ def iyuutest(request):
|
||||
"""
|
||||
|
||||
_id = request.POST.get('id','')
|
||||
|
||||
if _id == '':
|
||||
iyuu_key = request.POST.get('iyuu_key').strip()
|
||||
#if _id == '':
|
||||
|
||||
response_data={"code":0,"msg":"请先配置IYUU令牌或刷新页面"}
|
||||
#response_data={"code":0,"msg":"请先配置IYUU令牌或刷新页面"}
|
||||
|
||||
#else:
|
||||
|
||||
#ormdata = NotifyConfig.objects.get(id=_id)
|
||||
#iyuu_key = ormdata.iyuu_key
|
||||
|
||||
|
||||
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
|
||||
|
||||
now = datetime.datetime.now()
|
||||
time = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
headers = {
|
||||
'user_agent': user_agent,
|
||||
'Content-type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
now_time = parse.quote('<center><b><font color="#55a7e3">') + parse.unquote(time) + parse.quote('</font></b></center><br>')
|
||||
send_txts = parse.quote('<center><b><font color="#4CAF50">[测试]</font></b></center><br>')
|
||||
api = 'https://iyuu.cn/' + iyuu_key + '.send'
|
||||
sen_url = api + '?text='+ parse.quote('测试提示') + '&desp=' + now_time + send_txts
|
||||
response = requests.get(sen_url, headers=headers ,verify=False)
|
||||
|
||||
response_msg = json.loads(response.text)
|
||||
if response.status_code == 200 and response_msg['errcode'] == 0:
|
||||
response_data={"code":1,"msg":"发送测试成功"}
|
||||
else:
|
||||
|
||||
ormdata = NotifyConfig.objects.get(id=_id)
|
||||
iyuu_key = ormdata.iyuu_key
|
||||
|
||||
|
||||
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
|
||||
|
||||
now = datetime.datetime.now()
|
||||
time = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
headers = {
|
||||
'user_agent': user_agent,
|
||||
'Content-type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
now_time = parse.quote('<center><b><font color="#55a7e3">') + parse.unquote(time) + parse.quote('</font></b></center><br>')
|
||||
send_txts = parse.quote('<center><b><font color="#4CAF50">[测试]</font></b></center><br>')
|
||||
api = 'https://iyuu.cn/' + iyuu_key + '.send'
|
||||
sen_url = api + '?text='+ parse.quote('测试提示') + '&desp=' + now_time + send_txts
|
||||
response = requests.get(sen_url, headers=headers ,verify=False)
|
||||
|
||||
response_msg = json.loads(response.text)
|
||||
if response.status_code == 200 and response_msg['errcode'] == 0:
|
||||
response_data={"code":1,"msg":"发送测试成功"}
|
||||
else:
|
||||
response_data={"code":0,"msg":"发送测试失败,%s" % response_msg['errmsg'] }
|
||||
response_data={"code":0,"msg":"发送测试失败,%s" % response_msg['errmsg'] }
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
|
||||
0
apps/rss/__init__.py
Normal file
0
apps/rss/__init__.py
Normal file
3
apps/rss/admin.py
Normal file
3
apps/rss/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
apps/rss/apps.py
Normal file
6
apps/rss/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class RSSConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'rss'
|
||||
40
apps/rss/migrations/0001_initial.py
Normal file
40
apps/rss/migrations/0001_initial.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Generated by Django 4.1 on 2022-09-08 09:47
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('sites', '0014_alter_siteinfo_siteconfig_name_cn'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='FilmCategory',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name_en', models.CharField(max_length=20, verbose_name='英文名')),
|
||||
('name_cn', models.CharField(max_length=20, verbose_name='中文名')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FilmType',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=20, verbose_name='名称')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Config',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('url', models.URLField(blank=True, verbose_name='RSS地址')),
|
||||
('refresh_time', models.IntegerField(verbose_name='刷新间隔分钟')),
|
||||
('siteinfo_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='siteinfo', to='sites.siteinfo')),
|
||||
],
|
||||
),
|
||||
]
|
||||
25
apps/rss/migrations/0002_rule.py
Normal file
25
apps/rss/migrations/0002_rule.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.1 on 2022-09-08 17:04
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('download', '0002_alter_tools_name'),
|
||||
('rss', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Rule',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50, verbose_name='规则名称')),
|
||||
('keyword', models.CharField(max_length=100, null=True, verbose_name='关键字,使用逗号分隔')),
|
||||
('config_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='config', to='rss.config')),
|
||||
('tools_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tools', to='download.tools')),
|
||||
],
|
||||
),
|
||||
]
|
||||
23
apps/rss/migrations/0003_rule_status_alter_rule_name.py
Normal file
23
apps/rss/migrations/0003_rule_status_alter_rule_name.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.1 on 2022-09-08 19:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0002_rule'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='status',
|
||||
field=models.BooleanField(default=False, verbose_name='状态启用,禁用'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rule',
|
||||
name='name',
|
||||
field=models.CharField(max_length=50, unique=True, verbose_name='规则名称'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 4.1 on 2022-09-09 13:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0003_rule_status_alter_rule_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='config',
|
||||
name='refresh_time',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='refresh_time',
|
||||
field=models.IntegerField(default=5, verbose_name='刷新间隔分钟'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0005_rule_crontab_id.py
Normal file
18
apps/rss/migrations/0005_rule_crontab_id.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.1 on 2022-09-09 14:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0004_remove_config_refresh_time_rule_refresh_time'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='crontab_id',
|
||||
field=models.CharField(max_length=64, null=True, verbose_name='执行ID'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.1 on 2022-09-09 17:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cron', '0013_alter_job_sites'),
|
||||
('rss', '0005_rule_crontab_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='rule',
|
||||
name='crontab_id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='job_id',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='job', to='cron.job'),
|
||||
),
|
||||
]
|
||||
33
apps/rss/migrations/0007_seedinfo.py
Normal file
33
apps/rss/migrations/0007_seedinfo.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 10:36
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sites', '0014_alter_siteinfo_siteconfig_name_cn'),
|
||||
('rss', '0006_remove_rule_crontab_id_rule_job_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SeedInfo',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('seed_name', models.CharField(max_length=500, verbose_name='种子名称')),
|
||||
('seed_type', models.CharField(max_length=50, verbose_name='种子类型')),
|
||||
('seed_details_link', models.URLField(blank=True, verbose_name='种子详情地址')),
|
||||
('seed_published_time', models.DateField(verbose_name='发布时间')),
|
||||
('seed_hash_id', models.CharField(max_length=50, verbose_name='种子hash值')),
|
||||
('seed_donwload_link', models.URLField(blank=True, verbose_name='种子下载地址')),
|
||||
('seed_file_size', models.IntegerField(verbose_name='种子文件大小')),
|
||||
('seed_status', models.BooleanField(default=False, verbose_name='状态:下载,未下载')),
|
||||
('photos', models.URLField(blank=True, verbose_name='海报')),
|
||||
('douban_link', models.URLField(blank=True, verbose_name='豆瓣电影地址')),
|
||||
('imdb_link', models.URLField(blank=True, verbose_name='IMDB电影地址')),
|
||||
('siteinfo_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.siteinfo')),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0008_alter_config_url.py
Normal file
18
apps/rss/migrations/0008_alter_config_url.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 11:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0007_seedinfo'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='config',
|
||||
name='url',
|
||||
field=models.URLField(blank=True, max_length=350, verbose_name='RSS地址'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 11:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0008_alter_config_url'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='seedinfo',
|
||||
name='seed_published_time',
|
||||
field=models.DateTimeField(verbose_name='发布时间'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0010_alter_seedinfo_seed_file_size.py
Normal file
18
apps/rss/migrations/0010_alter_seedinfo_seed_file_size.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 11:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0009_alter_seedinfo_seed_published_time'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='seedinfo',
|
||||
name='seed_file_size',
|
||||
field=models.BigIntegerField(verbose_name='种子文件大小'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0011_alter_seedinfo_unique_together.py
Normal file
18
apps/rss/migrations/0011_alter_seedinfo_unique_together.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 12:20
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sites', '0014_alter_siteinfo_siteconfig_name_cn'),
|
||||
('rss', '0010_alter_seedinfo_seed_file_size'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='seedinfo',
|
||||
unique_together={('seed_hash_id', 'siteinfo_id')},
|
||||
),
|
||||
]
|
||||
19
apps/rss/migrations/0012_seedinfo_rule_id.py
Normal file
19
apps/rss/migrations/0012_seedinfo_rule_id.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 15:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0011_alter_seedinfo_unique_together'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='seedinfo',
|
||||
name='rule_id',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='rss.rule'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0013_seedinfo_seed_torrent_id.py
Normal file
18
apps/rss/migrations/0013_seedinfo_seed_torrent_id.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 16:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0012_seedinfo_rule_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='seedinfo',
|
||||
name='seed_torrent_id',
|
||||
field=models.IntegerField(null=True, verbose_name='在下载器的标识ID'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0014_rule_rate.py
Normal file
18
apps/rss/migrations/0014_rule_rate.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 20:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0013_seedinfo_seed_torrent_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='rate',
|
||||
field=models.CharField(max_length=10, null=True, verbose_name='码率:空,1080,2060'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0015_alter_rule_rate.py
Normal file
18
apps/rss/migrations/0015_alter_rule_rate.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 20:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0014_rule_rate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='rule',
|
||||
name='rate',
|
||||
field=models.CharField(default='all', max_length=10, verbose_name='码率:all,1080,2060'),
|
||||
),
|
||||
]
|
||||
18
apps/rss/migrations/0016_rule_is_paused.py
Normal file
18
apps/rss/migrations/0016_rule_is_paused.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-09-10 21:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rss', '0015_alter_rule_rate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='is_paused',
|
||||
field=models.BooleanField(default=False, verbose_name='是否立刻下载'),
|
||||
),
|
||||
]
|
||||
0
apps/rss/migrations/__init__.py
Normal file
0
apps/rss/migrations/__init__.py
Normal file
74
apps/rss/models.py
Normal file
74
apps/rss/models.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from django.db import models
|
||||
from sites.models import SiteInfo
|
||||
from download.models import Tools
|
||||
from cron.models import Job
|
||||
# Create your models here.
|
||||
|
||||
class FilmCategory(models.Model):
|
||||
"""影视类别"""
|
||||
name_en = models.CharField('英文名', max_length=20)
|
||||
name_cn = models.CharField('中文名', max_length=20)
|
||||
|
||||
class FilmType(models.Model):
|
||||
"""影视类型"""
|
||||
name = models.CharField('名称', max_length=20)
|
||||
|
||||
#class FilmActor(models.Model):
|
||||
#"""影视演员"""
|
||||
#name = models.CharField('名称', max_length=50)
|
||||
#name_en = models.CharField('英文名称', max_length=100)
|
||||
#constellation = models.CharField('星座', max_length=10)
|
||||
#gender = models.CharField('性别', max_length=2)
|
||||
#birth = models.DateField('出生日期')
|
||||
#birthplace = models.CharField('出生地', max_length=50)
|
||||
#job = models.CharField('职业', max_length=100)
|
||||
#description = models.TextField('简介')
|
||||
#avatar = models.URLField('头像', blank=True)
|
||||
|
||||
class Config(models.Model):
|
||||
"""RSS配置"""
|
||||
url = models.URLField('RSS地址', blank=True, max_length=350)
|
||||
#site_name = models.CharField('网站名简称,英文', max_length=50, unique=True)
|
||||
#site_name_cn = models.CharField('网站名简称,中文', max_length=50, unique=True)
|
||||
#on_update 和 on_delete 后面可以跟的词语有四个
|
||||
#1. no action 表示 不做任何操作,
|
||||
#2. set null 表示在外键表中将相应字段设置为null
|
||||
#3. set default 表示设置为默认值
|
||||
#4. cascade 表示级联操作,就是说,如果主键表中被参考字段更新,外键表中也更新,主键表中的记录被删除,外键表中改行也相应删除
|
||||
siteinfo_id = models.ForeignKey(SiteInfo, on_delete=models.CASCADE, related_name='siteinfo')
|
||||
|
||||
class Rule(models.Model):
|
||||
"""RSS规则"""
|
||||
name = models.CharField('规则名称', max_length=50, unique=True)
|
||||
config_id = models.ForeignKey(Config, on_delete=models.CASCADE, related_name='config')
|
||||
keyword = models.CharField('关键字,使用逗号分隔', max_length=100, null=True)
|
||||
tools_id = models.ForeignKey(Tools, on_delete=models.CASCADE, related_name='tools')
|
||||
status = models.BooleanField("状态启用,禁用",default=False)
|
||||
refresh_time = models.IntegerField('刷新间隔分钟', default=5)
|
||||
rate = models.CharField('码率:all,1080,2060', max_length=10, default='all')
|
||||
is_paused = models.BooleanField("是否立刻下载",default=False)
|
||||
|
||||
job_id = models.ForeignKey(Job, on_delete=models.CASCADE, related_name='job', null=True)
|
||||
|
||||
class SeedInfo(models.Model):
|
||||
"""种子信息"""
|
||||
seed_name = models.CharField('种子名称', max_length=500)
|
||||
seed_type = models.CharField('种子类型', max_length=50)
|
||||
seed_details_link = models.URLField('种子详情地址', blank=True)
|
||||
seed_published_time = models.DateTimeField('发布时间')
|
||||
seed_hash_id = models.CharField('种子hash值', max_length=50)
|
||||
seed_donwload_link = models.URLField('种子下载地址', blank=True)
|
||||
seed_file_size = models.BigIntegerField('种子文件大小')
|
||||
seed_status = models.BooleanField('状态:下载,未下载', default=False)
|
||||
seed_torrent_id = models.IntegerField("在下载器的标识ID", null=True)
|
||||
|
||||
photos = models.URLField('海报', blank=True)
|
||||
douban_link = models.URLField('豆瓣电影地址', blank=True)
|
||||
imdb_link = models.URLField('IMDB电影地址', blank=True)
|
||||
|
||||
siteinfo_id = models.ForeignKey(SiteInfo, on_delete=models.CASCADE)
|
||||
rule_id = models.ForeignKey(Rule, on_delete=models.CASCADE, null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together=("seed_hash_id", "siteinfo_id")
|
||||
|
||||
203
apps/rss/templates/rss/rssconfig.html
Normal file
203
apps/rss/templates/rss/rssconfig.html
Normal file
@@ -0,0 +1,203 @@
|
||||
<!-- 正文开始 -->
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
|
||||
<div class="layui-form toolbar">
|
||||
<div class="layui-form-item">
|
||||
|
||||
<div class="layui-inline searchInput">
|
||||
<input id="rssconfigSearchValue" class="layui-input" type="text" placeholder="输入关键字" />
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button id="rssconfigBtnSearch" class="layui-btn icon-btn"><i class="layui-icon"></i>搜索
|
||||
</button>
|
||||
<button id="rssconfigBtnAdd" class="layui-btn icon-btn"><i
|
||||
class="layui-icon"></i>添加</button>
|
||||
<button id="rssconfigBtnDel" class="layui-btn layui-btn-danger icon-btn"><i
|
||||
class="layui-icon"></i>删除</button>
|
||||
</button>
|
||||
此处仅配置不运行,需定制规则启动
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="layui-table" id="rssconfigTable" lay-filter="rssconfigTable"></table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 表格操作列 -->
|
||||
<script type="text/html" id="rssconfigTableBar">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'xmSelect', 'formX', 'dropdown', 'upload'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var upload = layui.upload;
|
||||
|
||||
form.render('select');
|
||||
// 渲染表格
|
||||
var insTb = tableX.render({
|
||||
elem: '#rssconfigTable',
|
||||
url: setter.base_server + 'rss/config/list',
|
||||
method: 'GET',
|
||||
page: true,
|
||||
limit: 15,
|
||||
limits: [15, 50, 100],
|
||||
cols: [[
|
||||
{ type: 'checkbox' },
|
||||
{ field: 'id', title: 'ID', hide: true },
|
||||
{ field: 'site_name', sort: true, title: '站点', width: 180 },
|
||||
{ field: 'url', sort: true, title: 'RSS地址' },
|
||||
{ align: 'center', toolbar: '#rssconfigTableBar', title: '操作', width: 150 }
|
||||
]]
|
||||
});
|
||||
|
||||
// 添加按钮点击事件
|
||||
$('#rssconfigBtnAdd').click(function () {
|
||||
showAddModel();
|
||||
});
|
||||
|
||||
// 工具条点击事件
|
||||
table.on('tool(rssconfigTable)', function (obj) {
|
||||
var data = obj.data;
|
||||
var layEvent = obj.event;
|
||||
|
||||
if (layEvent === 'edit') { // 修改
|
||||
showEditModel(data);
|
||||
} else if (layEvent === 'del') {
|
||||
|
||||
//var csrftoken = getCookie('csrftoken');
|
||||
layer.confirm('确定删除此记录 ' + data.name + '?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
$.ajax({
|
||||
url: "rss/config/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': [data.id], csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
// beforeSend: function(request) {
|
||||
// //django需要csrf验证,Forbidden (CSRF cookie not set.):
|
||||
// request.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
// },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssconfigTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//显示表单弹窗
|
||||
var showAddModel = function () {
|
||||
var title = '添加RSS订阅';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '300px'],
|
||||
url: 'rss/config/add',
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var showEditModel = function (data) {
|
||||
var title = '编辑';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '300px'],
|
||||
url: 'rss/config/edit?id=' + data.id,
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 批量删除按钮点击事件
|
||||
$('#rssconfigBtnDel').click(function () {
|
||||
//选中事件
|
||||
var checkStatus = table.checkStatus('rssconfigTable')
|
||||
//得到选择长度
|
||||
dataLength = checkStatus.data.length
|
||||
data = checkStatus.data;
|
||||
var ids = [];
|
||||
if (dataLength == 0) {
|
||||
//未选中
|
||||
layer.msg("请选择需要删除的记录", { icon: 2 });
|
||||
} else {
|
||||
layer.confirm('确定删除选中的' + dataLength + '个记录?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ids.push(data[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: "rss/config/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': ids, csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssconfigTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听enter键,光标在搜索框
|
||||
$('#rssconfigSearchValue').keydown(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
var key = 'search';
|
||||
var value = $('#rssconfigSearchValue').val();
|
||||
|
||||
table.reload('rssconfigTable', { where: { searchKey: key, searchValue: value } });
|
||||
} else if (event.keyCode === 8 && !$psw.val()) {
|
||||
$("#rssconfigSearchValue").val('');
|
||||
ptable();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
if (event.returnValue) event.returnValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索按钮点击事件
|
||||
$('#rssconfigBtnSearch').click(function () {
|
||||
var key = 'search';
|
||||
var value = $('#rssconfigSearchValue').val();
|
||||
|
||||
table.reload('rssconfigTable', { where: { searchKey: key, searchValue: value } });
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
87
apps/rss/templates/rss/rssconfigadd.html
Normal file
87
apps/rss/templates/rss/rssconfigadd.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="rssconfigAddForm" lay-filter="rssconfigAddForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">站点名称</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="siteinfo_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">RSS地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="url" type="text" class="layui-input" lay-verify="required|urlX"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="rssconfigAddForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'formX', 'dropdown'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
|
||||
|
||||
form.render('select', 'rssconfigAddForm');
|
||||
|
||||
var siteInfoIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#siteinfo_id',
|
||||
name: 'siteinfo_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('sites/siteinfo/select/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
siteInfoIDList.push({name: item.name, value: item.id});
|
||||
});
|
||||
insSel.update({
|
||||
data: siteInfoIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
form.on('submit(rssconfigAddForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('rss/config/add', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('rssconfigTable', {});
|
||||
admin.closeDialog('#rssconfigAddForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#rssconfigAddForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
93
apps/rss/templates/rss/rssconfigedit.html
Normal file
93
apps/rss/templates/rss/rssconfigedit.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="rssconfigEditForm" lay-filter="rssconfigEditForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
<input name="id" type="hidden" value="{{id}}"/>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">站点名称</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="siteinfo_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">RSS地址</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="url" type="text" class="layui-input" lay-verify="required|urlX" value="{{url}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="rssconfigEditForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'xmSelect', 'table', 'admin','formX'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var table = layui.table;
|
||||
var admin = layui.admin;
|
||||
|
||||
var formX = layui.formX;
|
||||
|
||||
|
||||
form.render('select',"rssconfigEditForm");
|
||||
|
||||
var siteInfoIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#siteinfo_id',
|
||||
name: 'siteinfo_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('sites/siteinfo/select/list?flag=1', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
|
||||
if ( item.id === {{siteinfo_id}} ){
|
||||
siteInfoIDList.push({name: item.name, value: item.id,selected: true});
|
||||
} else {
|
||||
siteInfoIDList.push({name: item.name, value: item.id});
|
||||
}
|
||||
|
||||
});
|
||||
insSel.update({
|
||||
data: siteInfoIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
form.on('submit(rssconfigEditForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
admin.req('rss/config/edit', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('rssconfigTable', {});
|
||||
admin.closeDialog('#rssconfigEditForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#rssconfigEditForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
241
apps/rss/templates/rss/rssrule.html
Normal file
241
apps/rss/templates/rss/rssrule.html
Normal file
@@ -0,0 +1,241 @@
|
||||
<!-- 正文开始 -->
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
|
||||
<div class="layui-form toolbar">
|
||||
<div class="layui-form-item">
|
||||
|
||||
<div class="layui-inline searchInput">
|
||||
<input id="rssruleSearchValue" class="layui-input" type="text" placeholder="输入关键字" />
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button id="rssruleBtnSearch" class="layui-btn icon-btn"><i class="layui-icon"></i>搜索
|
||||
</button>
|
||||
<button id="rssruleBtnAdd" class="layui-btn icon-btn"><i
|
||||
class="layui-icon"></i>添加</button>
|
||||
<button id="rssruleBtnDel" class="layui-btn layui-btn-danger icon-btn"><i
|
||||
class="layui-icon"></i>删除</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="layui-table" id="rssruleTable" lay-filter="rssruleTable"></table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 表格操作列 -->
|
||||
<script type="text/html" id="rssruleTableBar">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
{% verbatim myblock %}
|
||||
<!-- 表格状态列 -->
|
||||
<script type="text/html" id="rssruleTableState">
|
||||
<input type="checkbox" lay-filter="RssRuleState" value="{{d.id}}" lay-skin="switch"
|
||||
lay-text="启用|禁用" {{d.status==1?'checked':''}}/>
|
||||
</script>
|
||||
{% endverbatim myblock %}
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'xmSelect', 'formX', 'dropdown', 'upload'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var upload = layui.upload;
|
||||
|
||||
form.render('select');
|
||||
// 渲染表格
|
||||
var insTb = tableX.render({
|
||||
elem: '#rssruleTable',
|
||||
url: setter.base_server + 'rss/rule/list',
|
||||
method: 'GET',
|
||||
page: true,
|
||||
limit: 15,
|
||||
limits: [15, 50, 100],
|
||||
cols: [[
|
||||
{ type: 'checkbox' },
|
||||
{ field: 'id', title: 'ID', hide: true },
|
||||
{ field: 'name', sort: true, title: '名称', width: 120 },
|
||||
{ field: 'config_id', sort: true, title: '站点', width: 150 },
|
||||
{ field: 'tools_id', sort: true, title: '下载器', width: 200 },
|
||||
{ field: 'keyword', title: '关键字'},
|
||||
{ field: 'rate', title: '码率', width: 100},
|
||||
{ field: 'is_paused', title: '下载状态', width: 100, templet: function (d) {
|
||||
if (d.is_paused == 1){
|
||||
return "下载";
|
||||
}else{
|
||||
return "暂停";
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'refresh_time', sort: true, title: '刷新间隔', width: 110 },
|
||||
{ field: 'status', templet: '#rssruleTableState', title: '状态', width: 80 },
|
||||
{ align: 'center', toolbar: '#rssruleTableBar', title: '操作', width: 120 }
|
||||
]]
|
||||
});
|
||||
|
||||
// 添加按钮点击事件
|
||||
$('#rssruleBtnAdd').click(function () {
|
||||
showAddModel();
|
||||
});
|
||||
|
||||
// 工具条点击事件
|
||||
table.on('tool(rssruleTable)', function (obj) {
|
||||
var data = obj.data;
|
||||
var layEvent = obj.event;
|
||||
|
||||
if (layEvent === 'edit') { // 修改
|
||||
showEditModel(data);
|
||||
} else if (layEvent === 'del') {
|
||||
|
||||
//var csrftoken = getCookie('csrftoken');
|
||||
layer.confirm('确定删除此记录 ' + data.name + '?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
$.ajax({
|
||||
url: "rss/rule/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': [data.id], csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
// beforeSend: function(request) {
|
||||
// //django需要csrf验证,Forbidden (CSRF cookie not set.):
|
||||
// request.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
// },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssruleTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//显示表单弹窗
|
||||
var showAddModel = function () {
|
||||
var title = '添加';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '600px'],
|
||||
url: 'rss/rule/add',
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var showEditModel = function (data) {
|
||||
var title = '编辑';
|
||||
admin.open({
|
||||
title: title,
|
||||
area: ['600px', '600px'],
|
||||
url: 'rss/rule/edit?id=' + data.id,
|
||||
success: function (layero, index) {
|
||||
$(layero).children('.layui-layer-content').css('overflow', 'visible'); // 禁止出现滚动条
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 批量删除按钮点击事件
|
||||
$('#rssruleBtnDel').click(function () {
|
||||
//选中事件
|
||||
var checkStatus = table.checkStatus('rssruleTable')
|
||||
//得到选择长度
|
||||
dataLength = checkStatus.data.length
|
||||
data = checkStatus.data;
|
||||
var ids = [];
|
||||
if (dataLength == 0) {
|
||||
//未选中
|
||||
layer.msg("请选择需要删除的记录", { icon: 2 });
|
||||
} else {
|
||||
layer.confirm('确定删除选中的' + dataLength + '个记录?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ids.push(data[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: "rss/rule/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': ids, csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssruleTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听enter键,光标在搜索框
|
||||
$('#rssruleSearchValue').keydown(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
var key = 'search';
|
||||
var value = $('#rssruleSearchValue').val();
|
||||
|
||||
table.reload('rssruleTable', { where: { searchKey: key, searchValue: value } });
|
||||
} else if (event.keyCode === 8 && !$psw.val()) {
|
||||
$("#rssruleSearchValue").val('');
|
||||
ptable();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
if (event.returnValue) event.returnValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索按钮点击事件
|
||||
$('#rssruleBtnSearch').click(function () {
|
||||
var key = 'search';
|
||||
var value = $('#rssruleSearchValue').val();
|
||||
|
||||
table.reload('rssruleTable', { where: { searchKey: key, searchValue: value } });
|
||||
});
|
||||
|
||||
|
||||
// 修改规则状态
|
||||
form.on('switch(RssRuleState)', function (obj) {
|
||||
layer.load(2);
|
||||
admin.req('rss/rule/checkbox/setstatus', {
|
||||
id: obj.elem.value,
|
||||
value: obj.elem.checked ? 1 : 0,
|
||||
tag:'status'
|
||||
}, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
//table.reload('table-user', {});
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
$(obj.elem).prop('checked', !obj.elem.checked);
|
||||
form.render('checkbox');
|
||||
}
|
||||
}, 'GET');
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
207
apps/rss/templates/rss/rssruleadd.html
Normal file
207
apps/rss/templates/rss/rssruleadd.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="rssruleAddForm" lay-filter="rssruleAddForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="name" type="text" class="layui-input" lay-verify="required"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">RSS站点</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="config_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">下载器</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="tools_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关键字</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="keyword" type="text" class="layui-input" maxlength="100" placeholder="用于匹配影视,多个使用逗号分隔,不写为全部" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">码率</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="rate"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">刷新间隔</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="refresh_time" type="text" class="layui-input inline-block" lay-verify="numberX" min="1" maxlength="5"
|
||||
style="width: 160px;" placeholder="默认5分钟" />
|
||||
<span> 分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">立即下载</label>
|
||||
<div class="layui-inline-block" style="margin: 10px;">
|
||||
<input type="radio" name="is_paused" value="0" title="暂停" checked/>
|
||||
<input type="radio" name="is_paused" value="1" title="下载"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="status" lay-skin="switch" lay-text="启用|禁用"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">消息通知</label>
|
||||
|
||||
<div class="layui-inline-block" style="margin: 10px;">
|
||||
{{ notifys|safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="rssruleAddForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'formX', 'dropdown'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
|
||||
form.render('checkbox', 'rssruleAddForm');
|
||||
form.render('select', 'rssruleAddForm');
|
||||
form.render('radio');
|
||||
/*
|
||||
form.verify({
|
||||
keyword: [
|
||||
/^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$/
|
||||
,'用户名不能有特殊字符'
|
||||
]
|
||||
});
|
||||
*/
|
||||
var siteInfoIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#config_id',
|
||||
name: 'config_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('rss/config/select/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
siteInfoIDList.push({name: item.name, value: item.id});
|
||||
});
|
||||
insSel.update({
|
||||
data: siteInfoIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
var toolsIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var toolsSel = xmSelect.render({
|
||||
el: '#tools_id',
|
||||
name: 'tools_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('download/tools/select/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
|
||||
toolsIDList.push({name: item.name, value: item.id});
|
||||
});
|
||||
toolsSel.update({
|
||||
data: toolsIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
// 渲染多选下拉框
|
||||
var rateSel = xmSelect.render({
|
||||
el: '#rate',
|
||||
name: 'rate',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
data: [{'name':'all','value':'all', selected: true},
|
||||
{'name':'1080','value':'1080'},
|
||||
{'name':'2060','value':'2060'}
|
||||
]
|
||||
});
|
||||
|
||||
form.on('submit(rssruleAddForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
|
||||
//将页面全部复选框选中的值拼接到一个数组中
|
||||
var notifys_box = [];
|
||||
$('input[name="notifys"]:checked').each(function() {
|
||||
notifys_box.push($(this).val());
|
||||
});
|
||||
data.field.notifys = notifys_box
|
||||
|
||||
admin.req('rss/rule/add', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('rssruleTable', {});
|
||||
admin.closeDialog('#rssruleAddForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#rssruleAddForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
222
apps/rss/templates/rss/rssruleedit.html
Normal file
222
apps/rss/templates/rss/rssruleedit.html
Normal file
@@ -0,0 +1,222 @@
|
||||
<!-- 表单弹窗 -->
|
||||
<form id="rssruleEditForm" lay-filter="rssruleEditForm" class="layui-form model-form" method="POST">{% csrf_token %}
|
||||
<input name="id" type="hidden" value="{{id}}"/>
|
||||
<input name="crontab_id" type="hidden" value="{{crontab_id}}"/>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="name" type="text" class="layui-input" lay-verify="required" value="{{name}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">RSS站点</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="config_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">下载器</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="tools_id"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关键字</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="keyword" type="text" class="layui-input" maxlength="100"
|
||||
placeholder="用于匹配影视,多个使用逗号分隔,不写为全部" value="{{keyword}}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">刷新间隔</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="refresh_time" type="text" class="layui-input inline-block" lay-verify="numberX" min="1" maxlength="5"
|
||||
style="width: 160px;" placeholder="默认5分钟" value="{{refresh_time}}" />
|
||||
<span> 分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">立即下载</label>
|
||||
<div class="layui-inline-block" style="margin: 10px;">
|
||||
{% if is_paused %}
|
||||
<input type="radio" name="is_paused" value="0" title="暂停"/>
|
||||
<input type="radio" name="is_paused" value="1" title="下载" checked/>
|
||||
{% else %}
|
||||
<input type="radio" name="is_paused" value="0" title="暂停" checked/>
|
||||
<input type="radio" name="is_paused" value="1" title="下载"/>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">码率</label>
|
||||
<div class="layui-input-block">
|
||||
<div id="rate"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
{% if status == 1 %}
|
||||
<input type="checkbox" name="status" checked="" lay-skin="switch" lay-text="启用|禁用"/>
|
||||
{% else %}
|
||||
<input type="checkbox" name="status" lay-skin="switch" lay-text="启用|禁用"/>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">消息通知</label>
|
||||
|
||||
<div class="layui-inline-block" style="margin: 10px;">
|
||||
{{ notifys|safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item text-right">
|
||||
<button class="layui-btn layui-btn-primary" ew-event="closeDialog" type="button">取消</button>
|
||||
<button class="layui-btn" lay-filter="rssruleEditForm-submit" lay-submit>保存</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'xmSelect', 'table', 'admin','formX'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var table = layui.table;
|
||||
var admin = layui.admin;
|
||||
|
||||
var formX = layui.formX;
|
||||
|
||||
form.render('checkbox', 'rssruleEditForm');
|
||||
form.render('select',"rssruleEditForm");
|
||||
form.render('radio');
|
||||
|
||||
var siteInfoIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var insSel = xmSelect.render({
|
||||
el: '#config_id',
|
||||
name: 'config_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('rss/config/select/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
if ( item.id === {{config_id}} ){
|
||||
siteInfoIDList.push({name: item.name, value: item.id,selected: true});
|
||||
} else {
|
||||
siteInfoIDList.push({name: item.name, value: item.id});
|
||||
}
|
||||
|
||||
});
|
||||
insSel.update({
|
||||
data: siteInfoIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
var toolsIDList = [];
|
||||
// 渲染多选下拉框
|
||||
var toolsSel = xmSelect.render({
|
||||
el: '#tools_id',
|
||||
name: 'tools_id',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
filterable: true, //开启搜索
|
||||
data: []
|
||||
});
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('download/tools/select/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
|
||||
if ( item.id === {{tools_id}} ){
|
||||
toolsIDList.push({name: item.name, value: item.id,selected: true});
|
||||
} else {
|
||||
toolsIDList.push({name: item.name, value: item.id});
|
||||
}
|
||||
|
||||
});
|
||||
toolsSel.update({
|
||||
data: toolsIDList,
|
||||
autoRow: true,
|
||||
})
|
||||
} else {
|
||||
layer.msg(res.msg, {icon: 2});
|
||||
}
|
||||
});
|
||||
|
||||
// 渲染多选下拉框
|
||||
var rateSel = xmSelect.render({
|
||||
el: '#rate',
|
||||
name: 'rate',
|
||||
prop: {
|
||||
name: 'name',
|
||||
value: 'value',
|
||||
},
|
||||
layVerify: 'required',
|
||||
radio: true,
|
||||
clickClose: true,
|
||||
data: [{'name':'all','value':'all'},
|
||||
{'name':'1080','value':'1080'},
|
||||
{'name':'2060','value':'2060'}
|
||||
]
|
||||
});
|
||||
rateSel.setValue([ "{{rate}}" ])
|
||||
|
||||
form.on('submit(rssruleEditForm-submit)', function (data) {
|
||||
layer.load(2);
|
||||
|
||||
//将页面全部复选框选中的值拼接到一个数组中
|
||||
var notifys_box = [];
|
||||
$('input[name="notifys"]:checked').each(function() {
|
||||
notifys_box.push($(this).val());
|
||||
});
|
||||
data.field.notifys = notifys_box
|
||||
|
||||
admin.req('rss/rule/edit', data.field, function (data) {
|
||||
layer.closeAll('loading');
|
||||
if (data.code == 1) {
|
||||
layer.msg(data.msg, {icon: 1});
|
||||
table.reload('rssruleTable', {});
|
||||
admin.closeDialog('#rssruleEditForm');
|
||||
} else {
|
||||
layer.msg(data.msg, {icon: 2});
|
||||
}
|
||||
}, $('#rssruleEditForm').attr('method'));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
217
apps/rss/templates/rss/rssseedinfo.html
Normal file
217
apps/rss/templates/rss/rssseedinfo.html
Normal file
@@ -0,0 +1,217 @@
|
||||
<!-- 正文开始 -->
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
|
||||
<div class="layui-form toolbar">
|
||||
<div class="layui-form-item">
|
||||
|
||||
<div class="layui-inline searchInput">
|
||||
<input id="rssseedinfoSearchValue" class="layui-input" type="text" placeholder="输入关键字" />
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button id="rssseedinfoBtnSearch" class="layui-btn icon-btn"><i class="layui-icon"></i>搜索
|
||||
</button>
|
||||
<button id="rssseedinfoBtnDel" class="layui-btn layui-btn-danger icon-btn"><i
|
||||
class="layui-icon"></i>删除</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="layui-table" id="rssseedinfoTable" lay-filter="rssseedinfoTable"></table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 表格操作列 -->
|
||||
<script type="text/html" id="rssseedinfoTableBar">
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="download">下载</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use(['layer', 'form', 'table', 'tableX', 'util', 'admin', 'xmSelect', 'formX', 'dropdown', 'upload'], function () {
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
var form = layui.form;
|
||||
var table = layui.table;
|
||||
var tableX = layui.tableX;
|
||||
var util = layui.util;
|
||||
var admin = layui.admin;
|
||||
var formX = layui.formX;
|
||||
var setter = layui.setter;
|
||||
var xmSelect = layui.xmSelect;
|
||||
var upload = layui.upload;
|
||||
|
||||
form.render('select');
|
||||
// 渲染表格
|
||||
var insTb = tableX.render({
|
||||
elem: '#rssseedinfoTable',
|
||||
url: setter.base_server + 'rss/seedinfo/list',
|
||||
method: 'GET',
|
||||
page: true,
|
||||
limit: 15,
|
||||
limits: [15, 50, 100],
|
||||
cols: [[
|
||||
{ type: 'checkbox' },
|
||||
{ field: 'id', title: 'ID', hide: true },
|
||||
{ field: 'siteinfo_id', sort: true, title: '站点', width: 150 },
|
||||
{ field: 'seed_details_link', title: '种子介绍页', hide: true },
|
||||
{ field: 'seed_name', title: '名称', templet: function (d) {
|
||||
return '<a href="' + d.seed_details_link +'" target="_blank" id="test'+d.id+'" onmouseover="show('+ d.id +')"; onmouseleave="closeTips();">' + d.seed_name + '</a>';
|
||||
}, unresize: true
|
||||
},
|
||||
{ field: 'seed_type', sort: true, title: '类型', width: 150 },
|
||||
{ field: 'seed_published_time', title: '发布时间',sort: true, width: 170},
|
||||
{ field: 'seed_file_size', sort: true, title: '大小', width: 100},
|
||||
{ field: 'seed_status', title: '状态', width: 80, templet: function (d) {
|
||||
if (d.seed_status) {
|
||||
return '已下载';
|
||||
}else{
|
||||
return '未下载';
|
||||
}
|
||||
}
|
||||
},
|
||||
{ align: 'center', toolbar: '#rssseedinfoTableBar', title: '操作', width: 120 }
|
||||
]]
|
||||
});
|
||||
|
||||
|
||||
// 工具条点击事件
|
||||
table.on('tool(rssseedinfoTable)', function (obj) {
|
||||
var data = obj.data;
|
||||
var layEvent = obj.event;
|
||||
|
||||
if (layEvent === 'download') { // 下载
|
||||
layer.confirm('确定下载 ' + data.seed_name + '?', { icon: 1, title: '提示', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
$.ajax({
|
||||
url: "rss/seedinfo/donwload",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'id': data.id, csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssseedinfoTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else if (layEvent === 'del') {
|
||||
|
||||
//var csrftoken = getCookie('csrftoken');
|
||||
layer.confirm('确定删除此记录 ' + data.seed_name + '?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
$.ajax({
|
||||
url: "rss/seedinfo/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': [data.id], csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
// beforeSend: function(request) {
|
||||
// //django需要csrf验证,Forbidden (CSRF cookie not set.):
|
||||
// request.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
// },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssseedinfoTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 批量删除按钮点击事件
|
||||
$('#rssseedinfoBtnDel').click(function () {
|
||||
//选中事件
|
||||
var checkStatus = table.checkStatus('rssseedinfoTable')
|
||||
//得到选择长度
|
||||
dataLength = checkStatus.data.length
|
||||
data = checkStatus.data;
|
||||
var ids = [];
|
||||
if (dataLength == 0) {
|
||||
//未选中
|
||||
layer.msg("请选择需要删除的记录", { icon: 2 });
|
||||
} else {
|
||||
layer.confirm('确定删除选中的' + dataLength + '个记录?', { icon: 3, title: '警告', shadeClose: true },
|
||||
function (i) {
|
||||
layer.close(i);
|
||||
layer.load(2);
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ids.push(data[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: "rss/seedinfo/del",
|
||||
type: 'POST',
|
||||
dataType: "json",
|
||||
data: { 'ids': ids, csrfmiddlewaretoken: '{{ csrf_token }}' },
|
||||
success: function (d) {
|
||||
layer.closeAll('loading');
|
||||
if (d.code == 1) {
|
||||
table.reload('rssseedinfoTable', {});
|
||||
layer.msg(d.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(d.msg, { icon: 2 });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 监听enter键,光标在搜索框
|
||||
$('#rssseedinfoSearchValue').keydown(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
var key = 'search';
|
||||
var value = $('#rssseedinfoSearchValue').val();
|
||||
|
||||
table.reload('rssseedinfoTable', { where: { searchKey: key, searchValue: value } });
|
||||
} else if (event.keyCode === 8 && !$psw.val()) {
|
||||
$("#rssseedinfoSearchValue").val('');
|
||||
ptable();
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
if (event.returnValue) event.returnValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索按钮点击事件
|
||||
$('#rssseedinfoBtnSearch').click(function () {
|
||||
var key = 'search';
|
||||
var value = $('#rssseedinfoSearchValue').val();
|
||||
|
||||
table.reload('rssseedinfoTable', { where: { searchKey: key, searchValue: value } });
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
//悬停显示
|
||||
var tipsVal;
|
||||
function show(obj) {
|
||||
var node = "#test"+obj;
|
||||
//options : tips的配置型,即位置[1上;2右;3下;4左, 字体颜色]
|
||||
tipsVal=layer.tips("<div style='color:#000000;'>鼠标点击访问种子详情页</div>", node, {tips:[1,"#51a9e4"]});
|
||||
}
|
||||
|
||||
function closeTips() {//关闭显示的信息
|
||||
layer.close(tipsVal);
|
||||
}
|
||||
</script>
|
||||
3
apps/rss/tests.py
Normal file
3
apps/rss/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
1
apps/rss/urls/__init__.py
Normal file
1
apps/rss/urls/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
32
apps/rss/urls/views_urls.py
Normal file
32
apps/rss/urls/views_urls.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# coding:utf-8
|
||||
from django.urls import path
|
||||
from .. import views, views_request
|
||||
|
||||
app_name = 'rss'
|
||||
|
||||
urlpatterns = [
|
||||
# Resource asset path
|
||||
|
||||
#RSS配置
|
||||
path('config', views.RssConfigListView.as_view()),
|
||||
path('config/add', views.RssConfigAddView.as_view()),
|
||||
path('config/edit', views.RssConfigEditView.as_view()),
|
||||
path('config/del', views.RssConfigDelView.as_view()),
|
||||
path('config/list', views_request.config),
|
||||
path('config/select/list', views_request.select_rssconfig),
|
||||
|
||||
#RSS规则
|
||||
path('rule', views.RssRuleListView.as_view()),
|
||||
path('rule/add', views.RssRuleAddView.as_view()),
|
||||
path('rule/edit', views.RssRuleEditView.as_view()),
|
||||
path('rule/del', views.RssRuleDelView.as_view()),
|
||||
path('rule/list', views_request.rule),
|
||||
path('rule/checkbox/setstatus', views_request.checkbox_setRuleStatus),
|
||||
|
||||
#RSS种子详情
|
||||
path('seedinfo', views.RssSeedInfoListView.as_view()),
|
||||
path('seedinfo/del', views.RssSeedInfoDelView.as_view()),
|
||||
path('seedinfo/list', views_request.seedinfo),
|
||||
path('seedinfo/donwload', views_request.seed_download),
|
||||
]
|
||||
|
||||
455
apps/rss/views.py
Normal file
455
apps/rss/views.py
Normal file
@@ -0,0 +1,455 @@
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import TemplateView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import JsonResponse
|
||||
from django.db import transaction
|
||||
import uuid
|
||||
|
||||
from .models import Config, Rule, SeedInfo
|
||||
from sites.models import SiteInfo
|
||||
from download.models import Tools
|
||||
from cron.crontabs import my_scheduler
|
||||
from notify.models import NotifyConfig
|
||||
from cron.models import Job
|
||||
|
||||
# Create your views here.
|
||||
|
||||
class RssConfigListView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
显示
|
||||
"""
|
||||
template_name = 'rss/rssconfig.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
return super(RssConfigListView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
# 'data': self.ormdata_game
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssConfigListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class RssConfigAddView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
添加
|
||||
"""
|
||||
template_name = 'rss/rssconfigadd.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
"""
|
||||
return super(RssConfigAddView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssConfigAddView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
#数据提交接收方法
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
siteinfo_id = request.POST.get("siteinfo_id").strip()
|
||||
url = request.POST.get("url").strip()
|
||||
|
||||
ormdata_siteinfo = SiteInfo.objects.get(id=int(siteinfo_id))
|
||||
|
||||
ormdata = Config.objects.create(url=url,
|
||||
siteinfo_id=ormdata_siteinfo
|
||||
)
|
||||
|
||||
ormdata.save()
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class RssConfigEditView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
编辑域名
|
||||
"""
|
||||
template_name = 'rss/rssconfigedit.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
得到
|
||||
"""
|
||||
|
||||
#记录ID
|
||||
self._id = request.GET.get('id')
|
||||
self.ormdata = Config.objects.get(id=self._id)
|
||||
|
||||
return super(RssConfigEditView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
'id': self._id,
|
||||
'url': self.ormdata.url,
|
||||
'siteinfo_id': self.ormdata.siteinfo_id.id
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssConfigEditView, self).get_context_data(**kwargs)
|
||||
|
||||
#数据提交接收方法
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
url = request.POST.get("url").strip()
|
||||
siteinfo_id = request.POST.get("siteinfo_id").strip()
|
||||
|
||||
_id = request.POST.get('id')
|
||||
|
||||
ormdata_siteinfo = SiteInfo.objects.get(id=int(siteinfo_id))
|
||||
|
||||
ormdata = Config.objects.get(id=_id)
|
||||
|
||||
ormdata.url = url
|
||||
ormdata.siteinfo_id=ormdata_siteinfo
|
||||
|
||||
ormdata.save()
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class RssConfigDelView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
删除
|
||||
"""
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
|
||||
#得到批量或者单个要删除的id
|
||||
ids = request.POST.getlist("ids[]")
|
||||
#print("ids====>",ids)
|
||||
|
||||
Config.objects.filter(id__in=ids).delete()
|
||||
|
||||
#Site.objects.filter(id=i).delete()
|
||||
|
||||
response_data={"code":1,"msg":"操作成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
#==================
|
||||
class RssRuleListView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
显示
|
||||
"""
|
||||
template_name = 'rss/rssrule.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
return super(RssRuleListView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
# 'data': self.ormdata_game
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssRuleListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class RssRuleAddView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
添加
|
||||
"""
|
||||
template_name = 'rss/rssruleadd.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
"""
|
||||
return super(RssRuleAddView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
html_notifys = []
|
||||
notify_type = {'iyuu':'IYUU','telegram':'Telegram','email':'邮箱','enwechat':'企业微信'}
|
||||
|
||||
#获取通知配置
|
||||
notifys_count = NotifyConfig.objects.count()
|
||||
if notifys_count == 0:
|
||||
html_notifys.append('<b><span style="color: red;"><font size="2">请先配置通知</font></span></b>')
|
||||
else:
|
||||
for d in NotifyConfig.objects.all():
|
||||
html_notifys.append('<input type="checkbox" name="notifys" value="' + d.name +'" title="' + notify_type[d.name] + '"/>')
|
||||
|
||||
context = {
|
||||
'notifys':"".join(html_notifys),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssRuleAddView, self).get_context_data(**kwargs)
|
||||
|
||||
#事务回滚
|
||||
@transaction.atomic
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
name = request.POST.get("name").strip()
|
||||
config_id = request.POST.get("config_id").strip()
|
||||
keyword = request.POST.get("keyword").strip()
|
||||
tools_id = request.POST.get("tools_id").strip()
|
||||
status = request.POST.get("status")
|
||||
refresh_time = request.POST.get("refresh_time",'')
|
||||
notifys = request.POST.getlist("notifys[]")
|
||||
rate = request.POST.get("rate").strip()
|
||||
is_paused = request.POST.get("rate")
|
||||
|
||||
ormdata_config = Config.objects.get(id=int(config_id))
|
||||
ormdata_tools = Tools.objects.get(id=int(tools_id))
|
||||
#任务ID号
|
||||
crontab_id = str(uuid.uuid1())
|
||||
|
||||
if status == "on":
|
||||
status = 1
|
||||
else:
|
||||
status = 0
|
||||
|
||||
if refresh_time == '':
|
||||
refresh_time = 5
|
||||
|
||||
#创建任务
|
||||
#每几分运行
|
||||
crontab_time = '*/%s * * * *' % refresh_time
|
||||
|
||||
ormdata_job = Job.objects.create(name=name,
|
||||
jobtype_id=1002,
|
||||
crontab_time_type = "minute",
|
||||
crontab_status = status,
|
||||
minute = refresh_time,
|
||||
notifys = ",".join(notifys),
|
||||
crontab_time = crontab_time,
|
||||
crontab_id = crontab_id,
|
||||
|
||||
)
|
||||
ormdata_job.save()
|
||||
|
||||
#创建订阅规则
|
||||
ormdata_rule = Rule.objects.create(name=name,
|
||||
config_id=ormdata_config,
|
||||
tools_id=ormdata_tools,
|
||||
keyword=keyword,
|
||||
status = status,
|
||||
refresh_time = int(refresh_time),
|
||||
job_id = ormdata_job,
|
||||
rate = rate,
|
||||
is_paused = int(is_paused)
|
||||
)
|
||||
|
||||
ormdata_rule.save()
|
||||
|
||||
|
||||
#开始进行订阅操作
|
||||
minute = '*/%s' % refresh_time
|
||||
my_scheduler(crontab_id, status, minute=minute, jobtype_id=1002)
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class RssRuleEditView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
编辑域名
|
||||
"""
|
||||
template_name = 'rss/rssruleedit.html'
|
||||
|
||||
#显示添加模板
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
得到
|
||||
"""
|
||||
|
||||
#记录ID
|
||||
self._id = request.GET.get('id')
|
||||
self.ormdata = Rule.objects.get(id=self._id)
|
||||
|
||||
return super(RssRuleEditView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
html_notifys = []
|
||||
notify_type = {'iyuu':'IYUU','telegram':'Telegram','email':'邮箱','enwechat':'企业微信'}
|
||||
|
||||
ormdata_job = Job.objects.get(id=self.ormdata.job_id.id)
|
||||
|
||||
for d in NotifyConfig.objects.all():
|
||||
if d.name in ormdata_job.notifys:
|
||||
html_notifys.append('<input type="checkbox" name="notifys" value="' + d.name +'" title="' + notify_type[d.name] + '" checked />')
|
||||
else:
|
||||
html_notifys.append('<input type="checkbox" name="notifys" value="' + d.name +'" title="' + notify_type[d.name] + '"/>')
|
||||
|
||||
context = {
|
||||
'id': self._id,
|
||||
'name': self.ormdata.name,
|
||||
'config_id': self.ormdata.config_id.id,
|
||||
'tools_id': self.ormdata.tools_id.id,
|
||||
'keyword': self.ormdata.keyword,
|
||||
'status': self.ormdata.status,
|
||||
'refresh_time': self.ormdata.refresh_time,
|
||||
'notifys':"".join(html_notifys),
|
||||
'crontab_id': ormdata_job.crontab_id,
|
||||
'rate': self.ormdata.rate,
|
||||
'is_paused':self.ormdata.is_paused
|
||||
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssRuleEditView, self).get_context_data(**kwargs)
|
||||
|
||||
#数据提交接收方法
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
name = request.POST.get("name").strip()
|
||||
config_id = request.POST.get("config_id").strip()
|
||||
keyword = request.POST.get("keyword").strip()
|
||||
tools_id = request.POST.get("tools_id").strip()
|
||||
status = request.POST.get("status")
|
||||
refresh_time = request.POST.get("refresh_time",'')
|
||||
crontab_id = request.POST.get("crontab_id")
|
||||
rate = request.POST.get("rate")
|
||||
is_paused = request.POST.get("is_paused")
|
||||
notifys = request.POST.getlist("notifys[]")
|
||||
|
||||
_id = request.POST.get('id')
|
||||
|
||||
ormdata_config = Config.objects.get(id=int(config_id))
|
||||
ormdata_tools = Tools.objects.get(id=int(tools_id))
|
||||
|
||||
if status == "on":
|
||||
status = 1
|
||||
else:
|
||||
status = 0
|
||||
|
||||
if refresh_time == '':
|
||||
refresh_time = 5
|
||||
|
||||
ormdata = Rule.objects.get(id=_id)
|
||||
|
||||
ormdata.name = name
|
||||
ormdata.config_id=ormdata_config
|
||||
ormdata.tools_id = ormdata_tools
|
||||
ormdata.keyword = keyword
|
||||
ormdata.status = status
|
||||
ormdata.refresh_time = refresh_time
|
||||
ormdata.rate = rate
|
||||
ormdata.is_paused = int(is_paused)
|
||||
|
||||
ormdata.save()
|
||||
|
||||
crontab_time = '*/%s * * * *' % refresh_time
|
||||
Job.objects.filter(crontab_id=crontab_id).update(notifys=",".join(notifys),
|
||||
crontab_time = crontab_time,
|
||||
minute = refresh_time
|
||||
)
|
||||
|
||||
minute = '*/%s' % refresh_time
|
||||
my_scheduler(crontab_id = crontab_id, crontab_status = status, minute=minute, jobtype_id=1002 )
|
||||
|
||||
response_data={"code":1,"msg":"添加成功"}
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
class RssRuleDelView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
删除
|
||||
"""
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
|
||||
#得到批量或者单个要删除的id
|
||||
ids = request.POST.getlist("ids[]")
|
||||
#print("ids====>",ids)
|
||||
|
||||
#Rule.objects.filter(id__in=ids).delete()
|
||||
|
||||
for i in ids:
|
||||
_id = Rule.objects.get(id=i)
|
||||
#删除任务
|
||||
Job.objects.filter(id=_id.job_id.id).delete()
|
||||
#删除记录
|
||||
Rule.objects.filter(id=i).delete()
|
||||
#删除计划任务
|
||||
my_scheduler(crontab_id = _id.job_id.crontab_id, action="del")
|
||||
|
||||
response_data={"code":1,"msg":"操作成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
#==================
|
||||
class RssSeedInfoListView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
显示
|
||||
"""
|
||||
template_name = 'rss/rssseedinfo.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
return super(RssSeedInfoListView, self).get(request, *args, **kwargs)
|
||||
|
||||
#显示编辑模板
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = {
|
||||
# 'data': self.ormdata_game
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(RssSeedInfoListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class RssSeedInfoDelView(LoginRequiredMixin,TemplateView):
|
||||
"""
|
||||
删除
|
||||
"""
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
数据提交
|
||||
"""
|
||||
|
||||
#得到批量或者单个要删除的id
|
||||
ids = request.POST.getlist("ids[]")
|
||||
#print("ids====>",ids)
|
||||
|
||||
SeedInfo.objects.filter(id__in=ids).delete()
|
||||
|
||||
response_data={"code":1,"msg":"操作成功"}
|
||||
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
#==================
|
||||
339
apps/rss/views_request.py
Normal file
339
apps/rss/views_request.py
Normal file
@@ -0,0 +1,339 @@
|
||||
#coding=utf-8
|
||||
from django.http import JsonResponse, StreamingHttpResponse,HttpResponse
|
||||
from django.db.models import Q
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from transmission_rpc import Client
|
||||
import qbittorrentapi
|
||||
|
||||
from .models import Config, Rule, SeedInfo
|
||||
from cron.crontabs import my_scheduler
|
||||
from common.utils import filesizeformat, parseUrl
|
||||
|
||||
#直接使用检查是否管理员
|
||||
#from django.contrib.auth.decorators import user_passes_test
|
||||
#@user_passes_test(lambda u: u.is_superuser)
|
||||
|
||||
@login_required
|
||||
def config(request):
|
||||
"""
|
||||
提供相应的数据
|
||||
"""
|
||||
|
||||
#得到偏移量
|
||||
pageIndex= int(request.GET.get('page',1))
|
||||
#得到查询个数
|
||||
pageSize = int(request.GET.get('limit',10))
|
||||
|
||||
#搜索字段
|
||||
searchKey = request.GET.get('searchKey','')
|
||||
searchValue = request.GET.get('searchValue','')
|
||||
#去掉空格
|
||||
searchValue = searchValue.strip()
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
if searchValue == '':
|
||||
|
||||
data['count'] = Config.objects.count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Config.objects.order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Config.objects.order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
else:
|
||||
|
||||
data['count'] = Config.objects.filter(Q(name__icontains=searchValue)|Q(name_cn__icontains=searchValue)).count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Config.objects.filter(Q(name__icontains=searchValue)|Q(name_cn__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Config.objects.filter(Q(name__icontains=searchValue)|Q(name_cn__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({"id":i.id,
|
||||
"site_name":i.siteinfo_id.siteconfig_name + '(' + i.siteinfo_id.siteconfig_name_cn + ')',
|
||||
"url":i.url,
|
||||
})
|
||||
#返回json串
|
||||
#return HttpResponse(json.dumps(data,ensure_ascii = False), "application/json")
|
||||
return JsonResponse(data)
|
||||
|
||||
#===================================================================================================================
|
||||
@login_required
|
||||
def rule(request):
|
||||
"""
|
||||
提供相应的数据
|
||||
"""
|
||||
|
||||
#得到偏移量
|
||||
pageIndex= int(request.GET.get('page',1))
|
||||
#得到查询个数
|
||||
pageSize = int(request.GET.get('limit',10))
|
||||
|
||||
#搜索字段
|
||||
searchKey = request.GET.get('searchKey','')
|
||||
searchValue = request.GET.get('searchValue','')
|
||||
#去掉空格
|
||||
searchValue = searchValue.strip()
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
if searchValue == '':
|
||||
|
||||
data['count'] = Rule.objects.count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Rule.objects.order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Rule.objects.order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
else:
|
||||
|
||||
data['count'] = Rule.objects.filter(Q(name__icontains=searchValue)).count()
|
||||
if pageIndex == 1:
|
||||
ormdata = Rule.objects.filter(Q(name__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = Rule.objects.filter(Q(name__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({"id":i.id,
|
||||
#"config_id":i.config_id.siteinfo_id.siteconfig_name_cn,
|
||||
"config_id":i.config_id.siteinfo_id.siteconfig_name + '(' + i.config_id.siteinfo_id.siteconfig_name_cn + ')',
|
||||
"tools_id":i.tools_id.name,
|
||||
"name":i.name,
|
||||
"keyword":i.keyword,
|
||||
"status":i.status,
|
||||
"refresh_time":i.refresh_time,
|
||||
"rate":i.rate,
|
||||
"is_paused":i.is_paused
|
||||
})
|
||||
#返回json串
|
||||
#return HttpResponse(json.dumps(data,ensure_ascii = False), "application/json")
|
||||
return JsonResponse(data)
|
||||
|
||||
#===================================================================================================================
|
||||
@login_required
|
||||
def seedinfo(request):
|
||||
"""
|
||||
提供相应的数据
|
||||
"""
|
||||
|
||||
#得到偏移量
|
||||
pageIndex= int(request.GET.get('page',1))
|
||||
#得到查询个数
|
||||
pageSize = int(request.GET.get('limit',10))
|
||||
|
||||
#搜索字段
|
||||
searchKey = request.GET.get('searchKey','')
|
||||
searchValue = request.GET.get('searchValue','')
|
||||
#去掉空格
|
||||
searchValue = searchValue.strip()
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
if searchValue == '':
|
||||
|
||||
data['count'] = SeedInfo.objects.count()
|
||||
if pageIndex == 1:
|
||||
ormdata = SeedInfo.objects.order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = SeedInfo.objects.order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
else:
|
||||
|
||||
data['count'] = SeedInfo.objects.filter(Q(seed_name__icontains=searchValue)).count()
|
||||
if pageIndex == 1:
|
||||
ormdata = SeedInfo.objects.filter(Q(seed_name__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = SeedInfo.objects.filter(Q(seed_name__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({"id":i.id,
|
||||
"siteinfo_id":i.siteinfo_id.siteconfig_name + '(' + i.siteinfo_id.siteconfig_name_cn + ')',
|
||||
"seed_name":i.seed_name,
|
||||
"seed_type":i.seed_type,
|
||||
"seed_published_time":i.seed_published_time,
|
||||
"seed_file_size":filesizeformat(i.seed_file_size),
|
||||
"seed_status":i.seed_status,
|
||||
"seed_details_link":i.seed_details_link,
|
||||
})
|
||||
#返回json串
|
||||
#return HttpResponse(json.dumps(data,ensure_ascii = False), "application/json")
|
||||
return JsonResponse(data)
|
||||
#===================================================================================================================
|
||||
@login_required
|
||||
def checkbox_setRuleStatus(request):
|
||||
"""
|
||||
设置规则启用,禁用
|
||||
"""
|
||||
|
||||
_id = request.GET.get('id')
|
||||
value = request.GET.get('value')
|
||||
tag = request.GET.get('tag')
|
||||
|
||||
ormdata_rule = Rule.objects.get(id=_id)
|
||||
|
||||
if tag == 'status':
|
||||
#修改状态
|
||||
Rule.objects.filter(id=_id).update(status=int(value))
|
||||
if int(value) == 1:
|
||||
#激活任务
|
||||
minute = '*/%s' % ormdata_rule.refresh_time
|
||||
my_scheduler(crontab_id = ormdata_rule.job_id.crontab_id, crontab_status = True, minute=minute, jobtype_id=1002 )
|
||||
else:
|
||||
#禁用任务
|
||||
my_scheduler(crontab_id = ormdata_rule.job_id.crontab_id, action="del" )
|
||||
|
||||
data = {'code':1,'msg':'操作成功'}
|
||||
else:
|
||||
data = {'code':0,'msg':'未知操作'}
|
||||
|
||||
#返回json串
|
||||
#return HttpResponse(json.dumps(data,ensure_ascii = False), "application/json")
|
||||
return JsonResponse(data)
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def select_rssconfig(request):
|
||||
"""
|
||||
RSS订阅
|
||||
xmSelect
|
||||
"""
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
#获取数据标志 1 返回所有 其它返回未配置站点
|
||||
#flag = request.GET.get('flag', 0)
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
#获取所有记录
|
||||
data['count'] = Config.objects.count()
|
||||
|
||||
ormdata = Config.objects.order_by(order_by).all()
|
||||
|
||||
for i in ormdata:
|
||||
data['data'].append({
|
||||
"id":i.id,
|
||||
"name":i.siteinfo_id.siteconfig_name + "(" + i.siteinfo_id.siteconfig_name_cn + ")"
|
||||
})
|
||||
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def seed_download(request):
|
||||
"""
|
||||
下载种子
|
||||
"""
|
||||
#种子ID
|
||||
seed_id = request.POST.get("id")
|
||||
|
||||
ormdata_seedinfo = SeedInfo.objects.get(id = seed_id)
|
||||
#下载连接
|
||||
seed_donwload_link = ormdata_seedinfo.seed_donwload_link
|
||||
#下载器类型
|
||||
download_type = ormdata_seedinfo.rule_id.tools_id.typed
|
||||
download_username = ormdata_seedinfo.rule_id.tools_id.username
|
||||
download_password = ormdata_seedinfo.rule_id.tools_id.password
|
||||
download_url = ormdata_seedinfo.rule_id.tools_id.url
|
||||
#下载目录
|
||||
download_dirname = ormdata_seedinfo.rule_id.tools_id.dirname
|
||||
|
||||
if download_dirname == "":
|
||||
download_dirname = None
|
||||
|
||||
url_data = parseUrl(download_url)
|
||||
|
||||
if download_type == 'tr':
|
||||
try:
|
||||
|
||||
c = Client(protocol= url_data['protocol'],
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=download_username,
|
||||
password=download_password,
|
||||
timeout = 10
|
||||
)
|
||||
|
||||
torrent = c.add_torrent(seed_donwload_link,
|
||||
timeout = 10,
|
||||
download_dir = download_dirname
|
||||
|
||||
)
|
||||
#获取种子id
|
||||
torrent_id = torrent.id
|
||||
|
||||
ormdata_seedinfo.seed_torrent_id = torrent_id
|
||||
ormdata_seedinfo.seed_status = True
|
||||
ormdata_seedinfo.save()
|
||||
|
||||
response_data={"code":1,"msg": "添加成功" }
|
||||
except Exception as e:
|
||||
print(e)
|
||||
response_data={"code":0,"msg": "添加失败" }
|
||||
elif download_type == 'qb':
|
||||
|
||||
c = qbittorrentapi.Client(
|
||||
host=url_data['host'],
|
||||
port=url_data['port'],
|
||||
username=download_username,
|
||||
password=download_password,
|
||||
)
|
||||
|
||||
try:
|
||||
c.auth_log_in()
|
||||
response_data={"code":1,"msg": "添加成功" }
|
||||
except:
|
||||
response_data={"code":0,"msg": "添加失败" }
|
||||
|
||||
return JsonResponse(response_data)
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('sites/siteconfigname2siteinfo/list', function (res) {
|
||||
admin.req('sites/siteconfigname/list', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
/* 获取所有记录类型 */
|
||||
var loadIndex = layer.load(2);
|
||||
admin.req('sites/siteconfigname/list', function (res) {
|
||||
admin.req('sites/siteconfigname/list?flag=1', function (res) {
|
||||
layer.close(loadIndex);
|
||||
if (0 === res.code) {
|
||||
$.each(res.data, function (index, item) {
|
||||
|
||||
@@ -14,7 +14,6 @@ urlpatterns = [
|
||||
path('siteconfig/del', views.SiteConfigDelView.as_view()),
|
||||
path('siteconfig/list', views_request.siteconfig),
|
||||
path('siteconfigname/list', views_request.siteconfigname),
|
||||
path('siteconfigname2siteinfo/list', views_request.siteconfigname2siteinfo),
|
||||
path('siteconfig/export', views_request.siteconfigExport),
|
||||
path('siteconfig/import', views_request.siteconfigImport),
|
||||
#站点升级配置
|
||||
@@ -31,6 +30,7 @@ urlpatterns = [
|
||||
path('siteinfo/list', views_request.siteinfo),
|
||||
path('siteinfo/export', views_request.siteinfoExport),
|
||||
path('siteinfo/import', views_request.siteinfoImport),
|
||||
path('siteinfo/select/list', views_request.select_siteinfo),
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -370,9 +370,12 @@ class SiteInfoAddView(LoginRequiredMixin,TemplateView):
|
||||
cookie = request.POST.get("cookie").strip()
|
||||
passkey = request.POST.get("passkey").strip()
|
||||
|
||||
siteconfig_name_cn = list(SiteConfig.objects.filter(name=siteconfig_name).values_list('name_cn',flat=True))
|
||||
|
||||
ormdata = SiteInfo.objects.create(siteconfig_name=siteconfig_name,
|
||||
cookie=cookie,
|
||||
passkey=passkey,
|
||||
siteconfig_name_cn = siteconfig_name_cn[0]
|
||||
)
|
||||
|
||||
ormdata.save()
|
||||
@@ -423,12 +426,14 @@ class SiteInfoEditView(LoginRequiredMixin,TemplateView):
|
||||
|
||||
_id = request.POST.get('id')
|
||||
|
||||
siteconfig_name_cn = list(SiteConfig.objects.filter(name=siteconfig_name).values_list('name_cn',flat=True))
|
||||
|
||||
ormdata = SiteInfo.objects.get(id=_id)
|
||||
|
||||
ormdata.siteconfig_name = siteconfig_name
|
||||
ormdata.cookie = cookie
|
||||
ormdata.passkey = passkey
|
||||
|
||||
ormdata.siteconfig_name_cn = siteconfig_name_cn[0]
|
||||
|
||||
ormdata.save()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from django.db.models import Q
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from .models import SiteConfig, SiteRank, SiteInfo
|
||||
from rss.models import Config
|
||||
import simplejson as json
|
||||
import io
|
||||
from urllib import parse
|
||||
@@ -178,19 +179,19 @@ def siteinfo(request):
|
||||
ormdata = SiteInfo.objects.order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
else:
|
||||
|
||||
data['count'] = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)).count()
|
||||
data['count'] = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)|Q(siteconfig_name_cn__icontains=searchValue)).count()
|
||||
if pageIndex == 1:
|
||||
ormdata = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
ormdata = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)|Q(siteconfig_name_cn__icontains=searchValue)).order_by(order_by)[:pageSize] #offset:limit
|
||||
else:
|
||||
ormdata = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
ormdata = SiteInfo.objects.filter(Q(siteconfig_name__icontains=searchValue)|Q(siteconfig_name_cn__icontains=searchValue)).order_by(order_by)[pageSize*(pageIndex-1):pageIndex * pageSize]
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
siteconfig_ormdata = SiteConfig.objects.get(name=i.siteconfig_name)
|
||||
#siteconfig_ormdata = SiteConfig.objects.get(name=i.siteconfig_name)
|
||||
|
||||
data['data'].append({"id":i.id,
|
||||
"siteconfig_name":i.siteconfig_name,
|
||||
'siteconfig_name_cn':siteconfig_ormdata.name_cn,
|
||||
'siteconfig_name_cn':i.siteconfig_name_cn,
|
||||
"cookie":i.cookie,
|
||||
"passkey":i.passkey,
|
||||
})
|
||||
@@ -392,6 +393,7 @@ def siteinfoImport(request):
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def siteconfigname(request):
|
||||
@@ -405,6 +407,9 @@ def siteconfigname(request):
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
#获取数据标志 1 返回所有 其它返回未配置站点
|
||||
flag = request.GET.get('flag', 0)
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','name')
|
||||
#得到排序规则
|
||||
@@ -419,47 +424,12 @@ def siteconfigname(request):
|
||||
data['count'] = SiteConfig.objects.count()
|
||||
|
||||
ormdata = SiteConfig.objects.order_by(order_by).all()
|
||||
|
||||
|
||||
for i in ormdata:
|
||||
|
||||
data['data'].append({
|
||||
"name":i.name,
|
||||
"name_en_cn":i.name + "(" + i.name_cn + ")"
|
||||
})
|
||||
|
||||
return JsonResponse(data)
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def siteconfigname2siteinfo(request):
|
||||
"""
|
||||
网站集合,去掉已经创建的站点名称
|
||||
xmSelect
|
||||
"""
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','name')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
if int(flag) == 0:
|
||||
#获取siteinfo中配置的站点名
|
||||
ormdata_siteinfo = list(SiteInfo.objects.values_list('siteconfig_name', flat=True))
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
#获取所有记录
|
||||
data['count'] = SiteConfig.objects.count()
|
||||
|
||||
ormdata = SiteConfig.objects.order_by(order_by).all()
|
||||
|
||||
#获取siteinfo中配置的站点名
|
||||
ormdata_siteinfo = list(SiteInfo.objects.values_list('siteconfig_name', flat=True))
|
||||
ormdata_siteinfo = []
|
||||
|
||||
for i in ormdata:
|
||||
#忽略已经配置的站点
|
||||
@@ -469,4 +439,52 @@ def siteconfigname2siteinfo(request):
|
||||
"name_en_cn":i.name + "(" + i.name_cn + ")"
|
||||
})
|
||||
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
#==================
|
||||
@login_required
|
||||
def select_siteinfo(request):
|
||||
"""
|
||||
RSS订阅
|
||||
xmSelect
|
||||
"""
|
||||
|
||||
data = {}
|
||||
data['code'] = 0
|
||||
data['msg'] = ""
|
||||
data['data'] = []
|
||||
|
||||
#获取数据标志 1 返回所有 其它返回未配置站点
|
||||
flag = request.GET.get('flag', 0)
|
||||
|
||||
#得到排序字段
|
||||
sort = request.GET.get('sort','id')
|
||||
#得到排序规则
|
||||
order_by_type = request.GET.get('order','')
|
||||
|
||||
if order_by_type == 'asc':
|
||||
order_by = sort
|
||||
else:
|
||||
order_by = '-' + sort
|
||||
|
||||
#获取所有记录
|
||||
data['count'] = SiteInfo.objects.count()
|
||||
|
||||
ormdata = SiteInfo.objects.order_by(order_by).all()
|
||||
|
||||
if int(flag) == 0:
|
||||
#获取RSS配置的站点ID
|
||||
ormdata_config = list(Config.objects.values_list('siteinfo_id', flat=True))
|
||||
else:
|
||||
ormdata_config = []
|
||||
|
||||
for i in ormdata:
|
||||
#只返回未配置rss的站点
|
||||
if i.id not in ormdata_config:
|
||||
data['data'].append({
|
||||
"id":i.id,
|
||||
"name":i.siteconfig_name + "(" + i.siteconfig_name_cn + ")"
|
||||
})
|
||||
|
||||
return JsonResponse(data)
|
||||
Binary file not shown.
Binary file not shown.
@@ -17,6 +17,8 @@ thefuzz
|
||||
#thefuzz[speedup]
|
||||
#paddlepaddle
|
||||
paddleocr
|
||||
transmission-rpc
|
||||
qbittorrent-api
|
||||
#本地测试使用
|
||||
#PyMySQL >= 1.0.2
|
||||
#使用后台运行
|
||||
|
||||
@@ -49,6 +49,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "下载工具管理",
|
||||
"icon": "layui-icon layui-icon-set",
|
||||
"path": "javascript:;",
|
||||
"children": [
|
||||
{
|
||||
"title": "下载器配置",
|
||||
"path": "#/download/tools"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "消息推送配置",
|
||||
"icon": "layui-icon layui-icon-set",
|
||||
@@ -72,6 +83,25 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "RSS订阅管理",
|
||||
"icon": "layui-icon layui-icon-set",
|
||||
"path": "javascript:;",
|
||||
"children": [
|
||||
{
|
||||
"title": "RSS配置",
|
||||
"path": "#/rss/config"
|
||||
},
|
||||
{
|
||||
"title": "RSS规则",
|
||||
"path": "#/rss/rule"
|
||||
},
|
||||
{
|
||||
"title": "RSS种子详情",
|
||||
"path": "#/rss/seedinfo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "任务管理",
|
||||
"icon": "layui-icon layui-icon-set",
|
||||
|
||||
BIN
static/screenshot/rss.png
Normal file
BIN
static/screenshot/rss.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Reference in New Issue
Block a user