Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
karapoi committed Jul 1, 2023
0 parents commit baf00fc
Show file tree
Hide file tree
Showing 12 changed files with 1,598 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
config/
log/
torrents/
test/
data*/
upload/
__pycache__/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "gog-games"]
path = gog-games
url = https://github.com/GOG-Games-com/GOG.com-Game-Collection-Verification
73 changes: 73 additions & 0 deletions Configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# bug: a tale of paper: refold
# bug: cookie导入但未能登录
import configparser
import csv
import datetime
from time import strftime
import json

class Configuration:
def __init__(self):
self.get_config()

self.ignored_entries = []
self.completed_entries = []

self.records_file = 'log/records.csv'
self.records = []

def get_config(self):
with open('config/cookies.json', 'r') as r:
self.cookies = json.load(r)
self.pter_cookies = self.cookies['pter']
self.pic_cookies = self.cookies['pic']

config = configparser.ConfigParser()
config.read('config/config.ini')
self.upload_dir_on = (config['MODE']['upload_dir_on'] == 'True')
self.hlink_on = (config['MODE']['hlink_on'] == 'True')
self.proxies = config['MODE']['proxies']
self.use_pic_host = (config['MODE']['use_pic_host'] == 'True')
self.check_compressed = (config['MODE']['check_compressed'] == 'True')
self.comment = config['MODE']['comment']
self.passkey = config['PTER']['passkey']
self.announce = 'https://tracker.pterclub.com:443/announce?passkey=' + self.passkey
self.anonymous = 'yes' if config['PTER']['anonymous'] == 'True' else 'no'
self.torrent_dir = config['WORKDIR']['torrent_dir']
self.data_dir = config['WORKDIR']['data_dir']
self.upload_dir = config['WORKDIR']['upload_dir']
self.seed = (config['MODE']['seed'] == 'True')
self.client_type = config['CLIENT']['type']
self.client_ip = config['CLIENT']['ip']
self.client_port = config['CLIENT']['port']
self.client_username = config['CLIENT']['username']
self.client_password = config['CLIENT']['password']
self.save_path = config['CLIENT']['save_path']

def add_ignored_entry(self, entry_path):
if entry_path:
if not entry_path in self.ignored_entries:
self.ignored_entries.append(entry_path)

def remove_ignored_entry(self, entry_path):
if entry_path:
if entry_path in self.ignored_entries:
self.ignored_entries.remove(entry_path)

def add_completed_entry(self, entry_path):
if entry_path:
if not entry_path in self.completed_entries:
self.completed_entries.append(entry_path)

def remove_completed_entry(self, entry_path):
if entry_path:
if entry_path in self.completed_entries:
self.completed_entries.remove(entry_path)

def add_record(self, entry):
header = ['时间', '条目', '结果', '备注信息']
data = [{'时间':datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '条目':entry.path, '结果':entry.status, '备注信息':entry.info}]
self.records.append(data)
with open(self.records_file, mode='a', encoding='utf-8-sig', newline='') as record_f:
writer = csv.DictWriter(record_f, header)
writer.writerows(data)
358 changes: 358 additions & 0 deletions Entry.py

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions GameHashTable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import os
import re
import utils

class GameHashTable():
def __init__(self, logger):
self.logger = logger

self.src_dir = 'gog-games'
self.src = os.path.join(self.src_dir, 'gog_collection.sfv')
self.version = ''
self.htable = {}
self.ntable = {}
self._get_repo()
self._gen_hash_table()

# pull git repo
def _get_repo(self):
pass
#if not os.path.exists(self.src_dir):
# self.logger.info('-------- Cloning gog game repo ------------')
# os.system('git clone https://github.com/GOG-Games-com/GOG.com-Game-Collection-Verification')
# self.logger.info('----------------- Done --------------------')
#else:
# self.logger.info('-------- Updating gog game repo ------------')
# os.system('cd ' + self.src_dir + '; git fetch; git merge origin/main')
# self.logger.info('----------------- Done --------------------')

# create hash-game table from sfv file
def _gen_hash_table(self):
with open(self.src) as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if line:
file_hash = re.split('\s+', line)
if len(file_hash) == 2:
file = file_hash[0]
crc = file_hash[1]
game_filename = file.split('/', 1)
if len(game_filename) == 2:
game = game_filename[0]
filename = game_filename[1]
self.htable[crc] = game
self.ntable[filename] = game
else:
print('Failed to parse line:' + line)
self.version = os.popen('cd ' + self.src_dir + '; git rev-parse HEAD').read()

def update(self):
self._get_repo()
cur_version = os.popen('cd ' + self.src_dir + '; git rev-parse HEAD').read()
if cur_version != self.version:
self._gen_hash_table()

def search(self, crc):
crc = crc.lower()
if crc in self.htable.keys():
return self.htable[crc]
else:
return ''

def guess(self, game):
print(game)
for k in self.ntable.keys():
if game in k:
print('猜测到可能的游戏名为:', self.ntable[k])
right = utils.check_yes('是否正确[Y/[N]:')
if right:
return self.ntable[k]
return ''
135 changes: 135 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# gog2pter快捷转种工具![python](https://img.shields.io/badge/python-3.7-blue)![time](https://img.shields.io/github/last-commit/karapoi/gog2pter)<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)<!-- ALL-CONTRIBUTORS-BADGE:END -->

# 重要提示 Important Note
```diff
- 请勿以任何方式在此求邀(包括但不限于issue、discussion、PR)

- Plese don't ask for any invite here, this is not your place!
```

## 简介

该脚本能够在检测gog games下载的文件后自动获取相关信息并制作种子,同时自动将种子上传至PTerClub

---
## 工具特点
* 自动分析指定目录下的游戏文件,分析获取游戏名
* 自动制种,方便配合BT客户端实现自动做种
* 自动从gog商店获取游戏信息
* 自动新建PTer游戏条目
* 自动上传游戏种子
* 支持 `游戏本体` `Goodies`分别自动制种

## 依赖环境

### python模式

* Python 3
* Git
* Mac, Linux, Windows

## 安装指南

### Python 模式

#### 1.克隆我的仓库
由于项目依赖于GOG-Games-com/GOG.com-Game-Collection-Verification,请添加--recursive选项
~~~~shell
git clone --recursive https://github.com/karapoi/gog2pter.git
~~~~
#### 2.安装相关依赖
~~~~shell
pip install -r requirements.txt
~~~~
如果你无法安装的话可能是你的用户权限不够,尝试使用`sudo`安装;对于某些同时装有`python2``python3` 的用户,可能需要指明`pip`的版本,如 `pip3`
~~~~shell
sudo -H pip install -r requirements.txt
~~~~
#### 3.运行使用
##### 3.1 gog2pter
~~~~shell
mkdir config
python main.py
~~~~
另外可以使用以下命令来查看可以的命令选项和说明:
~~~~shell
python main.py --help
~~~~
##### 3.2 find games
发现可能尚未发布的游戏,注意最好发布前再手动搜索确认一次~
需要完成gog2pter的配置后才能使用。
~~~~shell
python find_games.py
~~~~
## 使用指南

### 1.填写配置信息
第一次运行时,程序会让你填写一些配置信息,按照实际情况填写即可:
* 猫站`cookies`
* 猫站`passkey`
* 匿名选项
* 数据目录(即自动检测的目录)
* 是否启用上传目录(强烈建议同硬链接模式一同启用)
* 是否启用硬链接模式(强烈建议启用)
* 种子目录(种子的保存目录)

### 2 填写cookies
第一次运行程序时,程序会让你输入猫站的cookies,按照提示输入即可:
![cookies.png](https://img.pterclub.com/images/2021/03/15/2021-03-15-223914.png)
cookies在登录猫站的情况下,按F12打开调试窗口,在控制台中输入document.cookie即可获得,注意不包括前后的引号。
也可按照常见问题所述方法获取。

### 3.等待程序运行

### 4.选择游戏信息
如果程序认为将要上传的种子的游戏信息可能已经存在于猫站,会返回一个列表让你选择游戏信息,如果不存在相关游戏的话,系统会自动上传到猫站。
```shell
我们在猫站找到以下游戏,请选择要上传的游戏分组(输入编号(并非gid)即可,如果没有请输入0):
1.Windows: Cooking Simulator GID:3409
编号: <输入编号>
```

### 5.输入种子额外信息
由于无法从gog获取游戏地区的相关信息,需要用户手动输入:
![moreinfo.png](https://img.pterclub.com/images/2021/03/15/2021-03-15-224809.png)

### 6.审查种子标题
脚本会自动检测主安装文件(即文件夹下符合set_*.exe命名的名字最短的文件)的名字并生成符合猫站规则的标题,但是仍然需要用户进行检查。如果有错误请输入正确的标题,无误则直接回车。

### 7.上传Goodies
脚本会自动检测目录下的zip或rar文件,并将其视作Goodies单独建立文件夹,单独制种,单独上传,其标题也需要用户进行检查。如果有错误请输入正确的标题,无误则直接回车。

### 8.上传完成

## 常见问题
* Q. cookies 是个什么东西呀?怎么获取呀?
* A. cookie 是来存储你登陆信息的一串字符,下面我以firefox为例演示一下怎么获取。
* * 按下F12进入开发者工具,并切换至`NETWORK/网络`栏目:
* * ![Network.png](https://img.pterclub.com/images/2021/03/22/10ac0ff23048ed11c.png)
* * 单击你左上角的用户名,载入你的用户界面
* * 找到`NEWWORK/网络`栏目里加载出来的user.php之类文件,并单击它:
* * ![user.php.png](https://img.pterclub.com/images/2021/03/23/2.png)
* * 找到`request header/请求头` 中cookie项目中的字段并复制下来:
* * ![cookies.png](https://img.pterclub.com/images/2021/03/22/3abed1483ad76c9a6.png)

-->

## 贡献者 ✨

脚本编写过程中大量参考了[ggn2pter](https://github.com/inerfire/ggn2pter),同时,部分内容参考了[happyfunc](https://github.com/inerfire/happyfunc)在此对原作者提出感谢。

感谢以下诸位的共同协作:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://github.com/karapoi"><img src="https://avatars.githubusercontent.com/u/9048968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>karapoi</b></sub></a><br /><a href="https://github.com/karapoi/gog2pter/commits?author=karapoi" title="Code">💻</a></td>
</tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->
91 changes: 91 additions & 0 deletions find_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import requests
import re
from bs4 import BeautifulSoup
import json
import time
import random

HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache', }

PTER_DOMAIN = 'https://pterclub.com/'

class PTerApi:
def __init__(self):
self.session = requests.Session()
self.session.headers = HEADERS
with open('config/cookies.json', 'r') as r:
self.cookies = json.load(r)
self.cookies = self.cookies['pter']
self._install_cookies()

# 加载cookie到session
def _install_cookies(self):
self.session.headers.update({'Referer': PTER_DOMAIN})
cookies = dict([field.split('=', 1) for field in self.cookies.split('; ')])
self.session.cookies = requests.utils.cookiejar_from_dict(cookies)

def find_game(self, name):
# 搜索游戏
url = PTER_DOMAIN + 'searchgameinfo.php'
data = {'name': name}
res = self.session.post(url, data=data)
res_soup = BeautifulSoup(res.text, 'lxml')
game_list = res_soup.select('a[title="点击发布这游戏设备的种子"]')
platform_list = res_soup.select('img[src^="/pic/category/chd/scenetorrents/"]')
if not game_list:
return False
else:
return True
#game_dict = {}
#num = 1
## 获取游戏列表
#for game, platform in zip(game_list[::2], platform_list):
# gid = re.search(r'detailsgameinfo.php\?id=(\d+)', game['href']).group(1)
# game_dict[str(num)] = '{}: {} GID:{}'.format(platform['title'], game.text, gid)
# num += 1
## 选择上传的目标游戏
#print('我们在猫站找到以下游戏:')
#for num, game in game_dict.items():
# print('{}.{}'.format(num, game))

def main():
games = []
with open('gog-games/gog_collection.sfv') as f:
lines = f.readlines()
for line in lines:
line = line.strip()
if line:
file_hash = re.split('\s+', line)
if len(file_hash) == 2:
file = file_hash[0]
crc = file_hash[1]
game_filename = file.split('/', 1)
if len(game_filename) == 2:
game = game_filename[0]
if len(game) > 4:
game = game.replace('_', ' ')
if not game in games:
games.append(game)
pter = PTerApi()
print('正在查找尚未发布的游戏...')
start = random.randint(1, len(games))
for i in range(start, len(games)):
game = games[i]
time.sleep(3)
if pter.find_game(game):
continue
else:
print('发现以下游戏可能尚未发布:' + game)
if input('是否继续,继续直接回车:'):
break


if __name__ == '__main__':
main()
Loading

0 comments on commit baf00fc

Please sign in to comment.