diff --git a/auto_pt/urls.py b/auto_pt/urls.py index 1f5b354..f26eb8e 100644 --- a/auto_pt/urls.py +++ b/auto_pt/urls.py @@ -11,5 +11,6 @@ urlpatterns = [ path(r'update', views.update_page, name='update_page'), path(r'do_restart', views.do_restart, name='do_restart'), path(r'do_update', views.do_update, name='do_update'), + path(r'import_from_ptpp', views.import_from_ptpp, name='import_from_ptpp'), path(r'do_sql', views.do_sql, name='do_sql'), ] diff --git a/auto_pt/views.py b/auto_pt/views.py index 312c826..83720f5 100644 --- a/auto_pt/views.py +++ b/auto_pt/views.py @@ -12,7 +12,7 @@ from pt_site import views as tasks from pt_site.UtilityTool import FileSizeConvert from pt_site.models import SiteStatus, MySite, Site from pt_site.views import scheduler, pt_spider -from ptools.base import CommonResponse +from ptools.base import CommonResponse, StatusCodeEnum def add_task(request): @@ -78,23 +78,80 @@ def test_notify(request): def do_sql(request): - # with open('main_pt_site_site.sql', encoding='utf-8') as file_obj: - # contents = file_obj.readlines() - # with connection.cursor() as cursor: - # for statement in contents: - # res1 = cursor.execute(statement) - # print(threading.main_thread().getName()) - try: - print(0) - except Exception as e: - - print(e) - # autoreload.start_django(au) - # django_main_thread - return JsonResponse('ok', safe=False) +def import_from_ptpp(request): + if request.method == 'GET': + return render(request, 'auto_pt/import_ptpp.html') + else: + # print(request.body) + data_list = json.loads(request.body).get('ptpp') + datas = json.loads(data_list) + print('content', len(datas)) + # success_messages = [] + # error_messages = [] + message_list = [] + # print(datas) + cookies = [] + cookie = { + 'domain': '', + 'cookies': '' + } + for index, data in enumerate(datas): + domain = data.get('domain').lstrip('.').lstrip('www.') + # print('domain', domain) + value = data.get('name') + '=' + data.get('value') + ';' + # print('value', value) + if not cookie.get('domain'): + cookie['domain'] = domain + cookie['cookies'] = value + elif domain in cookie.get('domain'): + # new_value = cookie['cookies'] + value + # cookie['cookies'] = new_value + cookie['cookies'] += value + # print('new_value', cookie['cookies']) + else: + cookie['cookies'] = cookie['cookies'].lstrip(';') + cookies.append(cookie) + # print(len(cookies)) + # cookie = {} + # cookie['domain'] = domain + # cookie['cookies'] = value + cookie = {'domain': domain, 'cookies': value} + if index == len(datas) - 1: + cookies.append(cookie) + # print('cookie:', cookie) + print('cookies,', len(cookies)) + for data in cookies: + try: + print(data) + res = pt_spider.get_uid_and_passkey(data) + msg = res.msg + print(msg) + if res.code == StatusCodeEnum.OK.code: + message_list.append({ + 'msg': msg, + 'tag': 'success' + }) + else: + # error_messages.append(msg) + message_list.append({ + 'msg': msg, + 'tag': 'error' + }) + except Exception as e: + message = '{} 站点导入失败!{} \n'.format(data.get('domain'), str(e)) + message_list.append({ + 'msg': message, + 'tag': 'warning' + }) + raise + return JsonResponse(CommonResponse.success(data={ + 'messages': message_list + }).to_dict(), safe=False) + + def get_git_logs(master='', n=10): # 获取最新的10条更新记录 # master='' 本地 master='origin/master' 远程 diff --git a/pt_site/UtilityTool.py b/pt_site/UtilityTool.py index ca28543..c978646 100644 --- a/pt_site/UtilityTool.py +++ b/pt_site/UtilityTool.py @@ -17,7 +17,7 @@ from wechat_push import WechatPush from wxpusher import WxPusher from auto_pt.models import Notify, OCR -from pt_site.models import MySite, SignIn, TorrentInfo, SiteStatus +from pt_site.models import MySite, SignIn, TorrentInfo, SiteStatus, Site from ptools.base import TorrentBaseInfo, PushConfig, CommonResponse, StatusCodeEnum @@ -94,6 +94,9 @@ class PtSpider: for i in list_mid: # 以第一个选中的字符分割1次, list2 = i.split('=', 1) + print(list2) + if list2[0] == '': + continue dist_dict[list2[0]] = list2[1] return dist_dict @@ -225,6 +228,40 @@ class PtSpider: msg=StatusCodeEnum.OCR_ACCESS_ERR.errmsg + str(e) ) + def get_uid_and_passkey(self, cookie: dict): + site = Site.objects.filter(url__contains=cookie.get('domain')).first() + # print('查询站点信息:',site) + if not site: + return CommonResponse.error(msg='尚未支持此站点:' + cookie.get('domain')) + my_site = MySite.objects.filter(site=site).first() + # print('查询我的站点:',my_site) + # 如果有更新cookie,如果没有继续创建 + if not my_site: + my_site = MySite( + site=site, + cookie=cookie.get('cookies') + ) + url = site.url + site.page_control_panel + # print(my_site.cookie) + print(url) + response = self.send_request(my_site=my_site, url=url) + # print(response.content.decode('utf8')) + user_details = self.parse(response, site.my_uid_rule) + print(user_details) + user_details_href = user_details[0] + passkey = self.parse(response, site.my_passkey_rule)[0] + uid = re.sub(r'\D', '', user_details_href) + print(uid, passkey) + my_site.user_id = uid + my_site.passkey = passkey + my_site.save() + print(site.name, uid, passkey) + return CommonResponse.success(msg=site.name + ' 信息导入成功!') + else: + my_site.cookie = cookie.get('cookies').rstrip(';') + my_site.save() + return CommonResponse.success(msg=site.name + ' 信息更新成功!') + def sign_in_hdsky(self, my_site: MySite, captcha=False): """HDSKY签到""" site = my_site.site diff --git a/pt_site/migrations/0001_initial.py b/pt_site/migrations/0001_initial.py index 3a218e6..23169b2 100644 --- a/pt_site/migrations/0001_initial.py +++ b/pt_site/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1 on 2022-08-25 13:16 +# Generated by Django 4.1 on 2022-09-09 08:11 import django.core.validators from django.db import migrations, models @@ -161,13 +161,16 @@ class Migration(migrations.Migration): "updated_at", models.DateTimeField(auto_now=True, verbose_name="更新时间"), ), - ("name", models.CharField(max_length=32, verbose_name="站点名称")), ( "url", models.URLField( - default="", help_text='请保留网址结尾的"/"', verbose_name="站点网址" + default="", + help_text='请保留网址结尾的"/"', + unique=True, + verbose_name="站点网址", ), ), + ("name", models.CharField(max_length=32, verbose_name="站点名称")), ( "logo", models.URLField( @@ -202,6 +205,12 @@ class Migration(migrations.Migration): default="attendance.php", max_length=64, verbose_name="默认签到链接" ), ), + ( + "page_control_panel", + models.CharField( + default="usercp.php", max_length=64, verbose_name="控制面板" + ), + ), ( "page_detail", models.CharField( @@ -374,7 +383,7 @@ class Migration(migrations.Migration): ( "title_rule", models.CharField( - default=".//tr/td[1]/text()", + default='.//td[@class="embedded"]/a/following::text()[1]', max_length=128, verbose_name="种子标题", ), @@ -390,7 +399,7 @@ class Migration(migrations.Migration): ( "category_rule", models.CharField( - default='.//td[@class="rowfollow nowrap"][1]/a[1]/img/@class', + default='.//td[@class="rowfollow nowrap"][1]/a[1]/img/@title', max_length=128, verbose_name="分类", ), @@ -406,9 +415,9 @@ class Migration(migrations.Migration): ( "magnet_url_rule", models.CharField( - default='.//td/a[contains(@href,"download")]/@href', + default='.//td/a[contains(@href,"download.php?id=")]/@href', max_length=128, - verbose_name="下载链接", + verbose_name="主页下载链接", ), ), ( @@ -416,7 +425,7 @@ class Migration(migrations.Migration): models.CharField( default='.//a[contains(@href,"download.php?id=") and contains(@href,"passkey")]/@href', max_length=128, - verbose_name="种子链接", + verbose_name="详情页种子链接", ), ), ( @@ -436,7 +445,7 @@ class Migration(migrations.Migration): ( "sale_rule", models.CharField( - default='.//table/tr/td/img[contains(@class,"pro_")]/@alt', + default='.//div/img[contains(@class,"pro_")]/@alt', max_length=128, verbose_name="促销信息", ), @@ -460,7 +469,7 @@ class Migration(migrations.Migration): ( "seeders_rule", models.CharField( - default=".//td[6]/b/a/text()", + default='.//a[contains(@href,"#seeders")]/text()', max_length=128, verbose_name="做种人数", ), @@ -468,7 +477,7 @@ class Migration(migrations.Migration): ( "leechers_rule", models.CharField( - default=".//td[7]/b/a/text()", + default='.//a[contains(@href,"#leechers")]/text()', max_length=128, verbose_name="下载人数", ), @@ -476,7 +485,7 @@ class Migration(migrations.Migration): ( "completers_rule", models.CharField( - default=".//td[8]/a/b/text()", + default='.//a[contains(@href,"viewsnatches.php?id=")]//text()', max_length=128, verbose_name="完成人数", ), @@ -498,9 +507,9 @@ class Migration(migrations.Migration): ( "peer_speed_rule", models.CharField( - default=".//tr/td[5]/nobr/text()", + default=".//tr/td[7]/nobr/text()", max_length=128, - verbose_name="平均上传速度", + verbose_name="平均下载速度", ), ), ( @@ -584,11 +593,27 @@ class Migration(migrations.Migration): ( "my_level_rule", models.CharField( - default='//span[@class="medium"]/span[@class="nowrap"]/a[contains(@class,"_Name")]/@class', + default='//a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=1")]/@class', max_length=128, verbose_name="用户等级", ), ), + ( + "my_passkey_rule", + models.CharField( + default='//td[contains(text(),"密钥")]/following-sibling::td[1]/text()', + max_length=128, + verbose_name="Passkey", + ), + ), + ( + "my_uid_rule", + models.CharField( + default='//a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=")]/@href', + max_length=128, + verbose_name="用户ID", + ), + ), ( "my_hr_rule", models.CharField( @@ -616,9 +641,10 @@ class Migration(migrations.Migration): ( "record_count_rule", models.CharField( - default="/html/body/b/text()", + default=".//td[3]/text()", + help_text="提取做种列表中文件大小计算总量", max_length=128, - verbose_name="种子记录数", + verbose_name="做种大小列表", ), ), ( @@ -633,12 +659,21 @@ class Migration(migrations.Migration): ( "mailbox_rule", models.CharField( - default='//a[@href="messages.php"]/following-sibling::text()[1]', + default='//a[@href="messages.php"]/font/text()', help_text="获取新邮件", max_length=128, verbose_name="邮件规则", ), ), + ( + "notice_rule", + models.CharField( + default='//a[@href="index.php"]/font/text()[1]', + help_text="获取新公告", + max_length=128, + verbose_name="公告规则", + ), + ), ( "hash_rule", models.CharField( @@ -712,7 +747,12 @@ class Migration(migrations.Migration): default="/downloads/brush", verbose_name="保存路径" ), ), - ("hr", models.BooleanField(default=False, verbose_name="H&R")), + ( + "hr", + models.BooleanField( + default=True, help_text="绿色为通过或无需HR考核", verbose_name="H&R考核" + ), + ), ( "sale_status", models.CharField(default="无促销", max_length=16, verbose_name="优惠状态"), @@ -797,14 +837,8 @@ class Migration(migrations.Migration): "updated_at", models.DateTimeField(auto_now=True, verbose_name="更新时间"), ), - ( - "uploaded", - models.CharField(default="0", max_length=16, verbose_name="上传量"), - ), - ( - "downloaded", - models.CharField(default="0", max_length=16, verbose_name="下载量"), - ), + ("uploaded", models.IntegerField(default=0, verbose_name="上传量")), + ("downloaded", models.IntegerField(default=0, verbose_name="下载量")), ("ratio", models.FloatField(default=0, verbose_name="分享率")), ("my_sp", models.FloatField(default=0, verbose_name="魔力值")), ("my_bonus", models.FloatField(default=0, verbose_name="做种积分")), @@ -844,6 +878,10 @@ class Migration(migrations.Migration): "sign_in_today", models.BooleanField(default=False, verbose_name="签到"), ), + ( + "sign_in_info", + models.CharField(default="", max_length=256, verbose_name="信息"), + ), ( "site", models.ForeignKey( diff --git a/pt_site/migrations/0002_alter_site_my_uid_rule.py b/pt_site/migrations/0002_alter_site_my_uid_rule.py new file mode 100644 index 0000000..4237736 --- /dev/null +++ b/pt_site/migrations/0002_alter_site_my_uid_rule.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1 on 2022-09-10 14:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("pt_site", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="site", + name="my_uid_rule", + field=models.CharField( + default='//a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=")]/@href', + max_length=128, + verbose_name="用户ID", + ), + ), + ] diff --git a/pt_site/migrations/0002_alter_site_url.py b/pt_site/migrations/0002_alter_site_url.py deleted file mode 100644 index 3d92cd0..0000000 --- a/pt_site/migrations/0002_alter_site_url.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1 on 2022-08-27 17:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("pt_site", "0001_initial"), - ] - - operations = [ - migrations.AlterField( - model_name="site", - name="url", - field=models.URLField( - default="", help_text='请保留网址结尾的"/"', unique=True, verbose_name="站点网址" - ), - ), - ] diff --git a/pt_site/migrations/0003_signin_sign_in_info.py b/pt_site/migrations/0003_signin_sign_in_info.py deleted file mode 100644 index 8b5a80d..0000000 --- a/pt_site/migrations/0003_signin_sign_in_info.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1 on 2022-09-02 11:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pt_site', '0002_alter_site_url'), - ] - - operations = [ - migrations.AddField( - model_name='signin', - name='sign_in_info', - field=models.CharField(default='', max_length=256, verbose_name='信息'), - ), - ] diff --git a/pt_site/migrations/0004_alter_site_category_rule_alter_site_completers_rule_and_more.py b/pt_site/migrations/0004_alter_site_category_rule_alter_site_completers_rule_and_more.py deleted file mode 100644 index ec0a6c5..0000000 --- a/pt_site/migrations/0004_alter_site_category_rule_alter_site_completers_rule_and_more.py +++ /dev/null @@ -1,63 +0,0 @@ -# Generated by Django 4.1 on 2022-09-02 17:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pt_site', '0003_signin_sign_in_info'), - ] - - operations = [ - migrations.AlterField( - model_name='site', - name='category_rule', - field=models.CharField(default='.//td[@class="rowfollow nowrap"][1]/a[1]/img/@title', max_length=128, verbose_name='分类'), - ), - migrations.AlterField( - model_name='site', - name='completers_rule', - field=models.CharField(default='.//a[contains(@href,"viewsnatches.php?id=")]//text()', max_length=128, verbose_name='完成人数'), - ), - migrations.AlterField( - model_name='site', - name='download_url_rule', - field=models.CharField(default='.//a[contains(@href,"download.php?id=") and contains(@href,"passkey")]/@href', max_length=128, verbose_name='详情页种子链接'), - ), - migrations.AlterField( - model_name='site', - name='leechers_rule', - field=models.CharField(default='.//a[contains(@href,"#leechers")]/text()', max_length=128, verbose_name='下载人数'), - ), - migrations.AlterField( - model_name='site', - name='magnet_url_rule', - field=models.CharField(default='.//td/a[contains(@href,"download.php?id=")]/@href', max_length=128, verbose_name='主页下载链接'), - ), - migrations.AlterField( - model_name='site', - name='peer_speed_rule', - field=models.CharField(default='.//tr/td[7]/nobr/text()', max_length=128, verbose_name='平均下载速度'), - ), - migrations.AlterField( - model_name='site', - name='record_count_rule', - field=models.CharField(default='.//td[3]/text()', help_text='提取做种列表中文件大小计算总量', max_length=128, verbose_name='做种大小列表'), - ), - migrations.AlterField( - model_name='site', - name='sale_rule', - field=models.CharField(default='.//div/img[contains(@class,"pro_")]/@alt', max_length=128, verbose_name='促销信息'), - ), - migrations.AlterField( - model_name='site', - name='seeders_rule', - field=models.CharField(default='.//a[contains(@href,"#seeders")]/text()', max_length=128, verbose_name='做种人数'), - ), - migrations.AlterField( - model_name='site', - name='title_rule', - field=models.CharField(default='.//td[@class="embedded"]/a/following::text()[1]', max_length=128, verbose_name='种子标题'), - ), - ] diff --git a/pt_site/migrations/0005_alter_torrentinfo_hr.py b/pt_site/migrations/0005_alter_torrentinfo_hr.py deleted file mode 100644 index b26008c..0000000 --- a/pt_site/migrations/0005_alter_torrentinfo_hr.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1 on 2022-09-02 17:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pt_site', '0004_alter_site_category_rule_alter_site_completers_rule_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='torrentinfo', - name='hr', - field=models.BooleanField(default=True, help_text='绿色为通过或无需HR考核', verbose_name='H&R考核'), - ), - ] diff --git a/pt_site/migrations/0006_site_notice_rule_alter_site_mailbox_rule.py b/pt_site/migrations/0006_site_notice_rule_alter_site_mailbox_rule.py deleted file mode 100644 index 4b3aab2..0000000 --- a/pt_site/migrations/0006_site_notice_rule_alter_site_mailbox_rule.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 4.1 on 2022-09-05 20:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("pt_site", "0005_alter_torrentinfo_hr"), - ] - - operations = [ - migrations.AddField( - model_name="site", - name="notice_rule", - field=models.CharField( - default='//a[@href="index.php"]/font/text()[1]', - help_text="获取新公告", - max_length=128, - verbose_name="公告规则", - ), - ), - migrations.AlterField( - model_name="site", - name="mailbox_rule", - field=models.CharField( - default='//a[@href="messages.php"]/font/text()', - help_text="获取新邮件", - max_length=128, - verbose_name="邮件规则", - ), - ), - ] diff --git a/pt_site/migrations/0007_alter_sitestatus_downloaded_and_more.py b/pt_site/migrations/0007_alter_sitestatus_downloaded_and_more.py deleted file mode 100644 index 37880f0..0000000 --- a/pt_site/migrations/0007_alter_sitestatus_downloaded_and_more.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.1 on 2022-09-06 16:36 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('pt_site', '0006_site_notice_rule_alter_site_mailbox_rule'), - ] - - operations = [ - migrations.AlterField( - model_name='sitestatus', - name='downloaded', - field=models.IntegerField(default=0, verbose_name='下载量'), - ), - migrations.AlterField( - model_name='sitestatus', - name='uploaded', - field=models.IntegerField(default=0, verbose_name='上传量'), - ), - ] diff --git a/pt_site/models.py b/pt_site/models.py index 90fe9b2..cec17c7 100644 --- a/pt_site/models.py +++ b/pt_site/models.py @@ -19,6 +19,7 @@ class Site(BaseEntity): # 主要页面 page_default = models.CharField(verbose_name='默认搜索页面', default='torrents.php', max_length=64) page_sign_in = models.CharField(verbose_name='默认签到链接', default='attendance.php', max_length=64) + page_control_panel = models.CharField(verbose_name='控制面板', default='usercp.php', max_length=64) page_detail = models.CharField(verbose_name='详情页面链接', default='details.php?id={}', max_length=64) page_download = models.CharField(verbose_name='默认下载链接', default='download.php?id={}', max_length=64) page_user = models.CharField(verbose_name='用户信息链接', default='userdetails.php?id={}', max_length=64) @@ -183,7 +184,17 @@ class Site(BaseEntity): max_length=128) my_level_rule = models.CharField( verbose_name='用户等级', - default='//span[@class="medium"]/span[@class="nowrap"]/a[contains(@class,"_Name")]/@class', + default='//a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=1")]/@class', + max_length=128 + ) + my_passkey_rule = models.CharField( + verbose_name='Passkey', + default='//td[contains(text(),"密钥")]/following-sibling::td[1]/text()', + max_length=128 + ) + my_uid_rule = models.CharField( + verbose_name='用户ID', + default='//a[contains(@class,"_Name") and contains(@href,"userdetails.php?id=")]/@href', max_length=128 ) my_hr_rule = models.CharField( diff --git a/ptools/settings.py b/ptools/settings.py index b61ff4b..071c5a7 100644 --- a/ptools/settings.py +++ b/ptools/settings.py @@ -204,12 +204,16 @@ SIMPLEUI_CONFIG = { }] }, { 'app': 'update', - 'name': '更新', - 'icon': 'fas fa-code', + 'name': '更新&导入', + 'icon': 'el-icon-attract', 'models': [{ - 'name': '更新', - 'icon': 'far fa-surprise', + 'name': '代码更新', + 'icon': 'el-icon-refresh', 'url': '/tasks/update' + }, { + 'name': '站点导入', + 'icon': 'el-icon-s-open', + 'url': '/tasks/import_from_ptpp' }, ] }] } diff --git a/templates/auto_pt/import_ptpp.html b/templates/auto_pt/import_ptpp.html new file mode 100644 index 0000000..ae303dc --- /dev/null +++ b/templates/auto_pt/import_ptpp.html @@ -0,0 +1,157 @@ +{% load static %} + + + + + {% include 'admin/includes/css-part.html' %} + + + +
+ +
+ + + + 导入 + {# #} + {# 点击上传#} + {# #} +
+
+ +
+ +
+
+ +{% include 'admin/includes/js-part.html' %} + + + + + \ No newline at end of file