Private GIT
Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CouchPotatoServer
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
vlbox
CouchPotatoServer
Commits
2cac21bd
Commit
2cac21bd
authored
Aug 11, 2012
by
Rembrand van Lakwijk
Committed by
Ruud
Sep 2, 2012
Browse files
Options
Downloads
Patches
Plain Diff
Initial commit off passthepopcorn search provider (port from version for CouchPotato 1)
parent
0cd2206e
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
couchpotato/core/providers/torrent/passthepopcorn/__init__.py
+36
-0
36 additions, 0 deletions
...hpotato/core/providers/torrent/passthepopcorn/__init__.py
couchpotato/core/providers/torrent/passthepopcorn/main.py
+273
-0
273 additions, 0 deletions
couchpotato/core/providers/torrent/passthepopcorn/main.py
with
309 additions
and
0 deletions
couchpotato/core/providers/torrent/passthepopcorn/__init__.py
0 → 100644
+
36
−
0
View file @
2cac21bd
from
main
import
PassThePopcorn
def
start
():
return
PassThePopcorn
()
config
=
[{
'
name
'
:
'
passthepopcorn
'
,
'
groups
'
:
[{
'
tab
'
:
'
searcher
'
,
'
subtab
'
:
'
providers
'
,
'
name
'
:
'
PassThePopcorn
'
,
'
description
'
:
'
passthepopcorn.me
'
,
'
options
'
:
[
{
'
name
'
:
'
enabled
'
,
'
type
'
:
'
enabler
'
,
'
default
'
:
False
},
{
'
name
'
:
'
domain
'
,
'
advanced
'
:
True
,
'
label
'
:
'
Proxy server
'
,
'
description
'
:
'
Domain for requests (HTTPS only!), keep empty to use default (tls.passthepopcorn.me).
'
,
},
{
'
name
'
:
'
username
'
,
'
default
'
:
''
,
},
{
'
name
'
:
'
password
'
,
'
default
'
:
''
,
'
type
'
:
'
password
'
,
}
],
}]
}]
This diff is collapsed.
Click to expand it.
couchpotato/core/providers/torrent/passthepopcorn/main.py
0 → 100644
+
273
−
0
View file @
2cac21bd
from
bs4
import
BeautifulSoup
from
couchpotato.core.event
import
fireEvent
from
couchpotato.core.helpers.encoding
import
toUnicode
from
couchpotato.core.helpers.variable
import
getTitle
,
getImdb
,
tryInt
,
cleanHost
from
couchpotato.core.logger
import
CPLog
from
couchpotato.core.providers.torrent.base
import
TorrentProvider
from
couchpotato.environment
import
Env
from
dateutil.parser
import
parse
import
os
import
time
import
re
import
htmlentitydefs
import
urllib
import
urllib2
import
cookielib
import
json
log
=
CPLog
(
__name__
)
class
PassThePopcorn
(
TorrentProvider
):
urls
=
{
'
detail
'
:
'
%s/torrent/%s
'
,
'
search
'
:
'
%s/search/%s/0/7/%d
'
}
disable_provider
=
False
domain
=
'
tls.passthepopcorn.me
'
opener
=
None
cookiejar
=
None
quality_search_params
=
{
'
1080p
'
:
{
'
resolution
'
:
'
1080p
'
},
'
720p
'
:
{
'
resolution
'
:
'
720p
'
},
'
brrip
'
:
{
'
media
'
:
'
Blu-ray
'
},
# results are filtered by post_search_filters to narrow down the search
'
dvdr
'
:
{
'
resolution
'
:
'
anysd
'
},
# results are filtered by post_search_filters to narrow down the search
'
dvdrip
'
:
{
'
media
'
:
'
DVD
'
},
# results are filtered by post_search_filters to narrow down the search
'
scr
'
:
{
'
media
'
:
'
DVD-Screener
'
},
'
r5
'
:
{
'
media
'
:
'
R5
'
},
'
tc
'
:
{
'
media
'
:
'
TC
'
},
'
ts
'
:
{
'
media
'
:
'
TS
'
},
'
cam
'
:
{
'
media
'
:
'
CAM
'
}
}
post_search_filters
=
{
'
1080p
'
:
{
'
Resolution
'
:
[
'
1080p
'
]},
'
720p
'
:
{
'
Resolution
'
:
[
'
720p
'
]},
'
brrip
'
:
{
'
Source
'
:
[
'
Blu-ray
'
],
'
Quality
'
:
[
'
High Definition
'
],
'
Container
'
:
[
'
!ISO
'
]},
'
dvdr
'
:
{
'
Codec
'
:
[
'
DVD5
'
,
'
DVD9
'
]},
'
dvdrip
'
:
{
'
Source
'
:
[
'
DVD
'
],
'
Codec
'
:
[
'
!DVD5
'
,
'
!DVD9
'
]},
'
scr
'
:
{
'
Source
'
:
[
'
DVD-Screener
'
]},
'
r5
'
:
{
'
Source
'
:
[
'
R5
'
]},
'
tc
'
:
{
'
Source
'
:
[
'
TC
'
]},
'
ts
'
:
{
'
Source
'
:
[
'
TS
'
]},
'
cam
'
:
{
'
Source
'
:
[
'
CAM
'
]}
}
class
NotLoggedInHTTPError
(
urllib2
.
HTTPError
):
def
__init__
(
self
,
url
,
code
,
msg
,
headers
,
fp
):
urllib2
.
HTTPError
.
__init__
(
self
,
url
,
code
,
msg
,
headers
,
fp
)
class
PTPHTTPRedirectHandler
(
urllib2
.
HTTPRedirectHandler
):
def
http_error_302
(
self
,
req
,
fp
,
code
,
msg
,
headers
):
log
.
debug
(
"
302 detected; redirected to %s
"
%
headers
[
'
Location
'
])
if
(
headers
[
'
Location
'
]
!=
'
login.php
'
):
#log.info("Redirect NOT due to not being logged in detected; allowing redirect")
return
urllib2
.
HTTPRedirectHandler
.
http_error_302
(
self
,
req
,
fp
,
code
,
msg
,
headers
)
else
:
#log.info("NotLoggedInHTTPError detected; raising it")
raise
PassThePopcorn
.
NotLoggedInHTTPError
(
req
.
get_full_url
(),
code
,
msg
,
headers
,
fp
)
def
__init__
(
self
):
cookieprocessor
=
urllib2
.
HTTPCookieProcessor
(
self
.
cookiejar
)
self
.
cookiejar
=
cookielib
.
CookieJar
()
self
.
opener
=
urllib2
.
build_opener
(
cookieprocessor
,
PassThePopcorn
.
PTPHTTPRedirectHandler
())
self
.
opener
.
addheaders
=
[
(
'
User-Agent
'
,
'
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.75 Safari/537.1
'
),
(
'
Accept
'
,
'
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
'
),
(
'
Accept-Language
'
,
'
en-gb,en;q=0.5
'
),
(
'
Accept-Charset
'
,
'
ISO-8859-1,utf-8;q=0.7,*;q=0.7
'
),
(
'
Keep-Alive
'
,
'
115
'
),
(
'
Connection
'
,
'
keep-alive
'
),
(
'
Cache-Control
'
,
'
max-age=0
'
),
]
self
.
domain
=
self
.
conf
(
'
domain
'
)
if
self
.
conf
(
'
domain
'
)
else
self
.
domain
super
(
PassThePopcorn
,
self
).
__init__
()
def
login
(
self
):
log
.
info
(
"
Trying to log into passthepopcorn.me...
"
)
url
=
'
https://%s/login.php
'
%
(
self
.
domain
)
postdata
=
urllib
.
urlencode
({
'
username
'
:
self
.
conf
(
'
username
'
),
'
password
'
:
self
.
conf
(
'
password
'
),
'
keeplogged
'
:
'
1
'
,
'
login
'
:
'
Login
'
})
try
:
response
=
self
.
opener
.
open
(
url
,
postdata
)
log
.
debug
(
'
Login POST did not throw exception
'
)
except
urllib2
.
URLError
as
e
:
log
.
error
(
'
Login to passthepopcorn failed: %s
'
%
e
)
return
False
if
response
.
getcode
()
==
200
:
log
.
info
(
'
Login HTTP status 200; seems successful
'
)
return
True
else
:
log
.
error
(
'
Login to passthepopcorn failed: returned code %d
'
%
response
.
getcode
())
return
False
def
protected_request
(
self
,
url
):
log
.
debug
(
'
Retrieving %s
'
%
url
)
maxattempts
=
3
while
maxattempts
>
0
:
try
:
response
=
self
.
opener
.
open
(
url
)
txt
=
response
.
read
()
#log.info('Response was:\n %s' % jsontxt)
if
response
.
getcode
()
!=
200
:
log
.
error
(
'
Retrieving
\'
%s
\'
resulted in HTTP response code %d
'
%
(
url
,
response
.
getcode
()))
return
None
return
txt
except
PassThePopcorn
.
NotLoggedInHTTPError
as
e
:
if
not
self
.
login
():
# if we can login, just retry
log
.
error
(
'
Login failed, could not execute request %s
'
%
url
)
return
None
log
.
debug
(
"
Should now be logged into passthepopcorn.me, trying request again...
"
)
except
urllib2
.
URLError
as
e
:
log
.
error
(
'
Retrieving JSON from url %s failed: %s
'
%
(
url
,
e
))
return
None
maxattempts
=
maxattempts
-
1
def
json_request
(
self
,
path
,
params
):
url
=
'
https://%s/%s?json=noredirect&%s
'
%
(
self
.
domain
,
path
,
urllib
.
urlencode
(
params
))
txt
=
self
.
protected_request
(
url
)
if
txt
:
return
json
.
loads
(
txt
)
else
:
return
None
def
enabled
(
self
):
return
(
not
self
.
isDisabled
()
and
\
self
.
conf
(
'
username
'
)
and
\
self
.
conf
(
'
password
'
))
def
torrent_meets_quality_spec
(
self
,
torrent
,
quality
):
if
not
quality
in
self
.
post_search_filters
:
return
True
for
field
,
specs
in
self
.
post_search_filters
[
quality
].
items
():
matchesOne
=
False
seenOne
=
False
if
not
field
in
torrent
:
log
.
info
(
'
Torrent with ID %s has no field
"
%s
"
; cannot apply post-search-filter for quality
"
%s
"'
%
(
torrent
[
'
Id
'
],
field
,
quality
))
continue
for
spec
in
specs
:
if
len
(
spec
)
>
0
and
spec
[
0
]
==
'
!
'
:
# a negative rule; if the field matches, return False
if
torrent
[
field
]
==
spec
[
1
:]:
return
False
else
:
# a positive rule; if any of the possible positive values match the field, return True
seenOne
=
True
if
torrent
[
field
]
==
spec
:
matchesOne
=
True
if
seenOne
and
not
matchesOne
:
return
False
return
True
def
htmltounicode
(
self
,
text
):
def
fixup
(
m
):
text
=
m
.
group
(
0
)
if
text
[:
2
]
==
"
&#
"
:
# character reference
try
:
if
text
[:
3
]
==
"
&#x
"
:
return
unichr
(
int
(
text
[
3
:
-
1
],
16
))
else
:
return
unichr
(
int
(
text
[
2
:
-
1
]))
except
ValueError
:
pass
else
:
# named entity
try
:
text
=
unichr
(
htmlentitydefs
.
name2codepoint
[
text
[
1
:
-
1
]])
except
KeyError
:
pass
return
text
# leave as is
return
re
.
sub
(
"
&#?\w+;
"
,
fixup
,
u
'
%s
'
%
text
)
def
unicodetoascii
(
self
,
text
):
import
unicodedata
return
''
.
join
(
c
for
c
in
unicodedata
.
normalize
(
'
NFKD
'
,
text
)
if
unicodedata
.
category
(
c
)
!=
'
Mn
'
)
def
htmltoascii
(
self
,
text
):
return
self
.
unicodetoascii
(
self
.
htmltounicode
(
text
))
def
download
(
self
,
url
=
''
,
nzb_id
=
''
):
return
self
.
protected_request
(
url
)
def
search
(
self
,
movie
,
quality
):
movieTitle
=
getTitle
(
movie
[
'
library
'
])
qualityID
=
quality
[
'
identifier
'
]
imdbID
=
movie
[
'
library
'
][
'
info
'
][
'
imdb
'
]
movieYear
=
movie
[
'
library
'
][
'
info
'
][
'
year
'
]
log
.
info
(
'
Searching for %s
'
%
movieTitle
)
if
not
self
.
enabled
():
log
.
info
(
'
PTP not enabled, skipping search
'
)
return
[]
params
=
[]
if
qualityID
:
params
=
self
.
quality_search_params
[
qualityID
]
if
imdbID
:
params
[
'
searchstr
'
]
=
imdbID
else
:
params
[
'
searchstr
'
]
=
movieTitle
params
[
'
year
'
]
=
movieYear
params
[
'
order_by
'
]
=
'
relevance
'
params
[
'
order_way
'
]
=
'
descending
'
res
=
self
.
json_request
(
'
torrents.php
'
,
params
)
if
not
res
:
log
.
error
(
'
Search on passthepopcorn.me (%s) failed
'
%
params
)
return
[]
#log.info('JSON: %s' % json.dumps(res))
if
not
'
Movies
'
in
res
:
return
[]
results
=
[]
for
ptpmovie
in
res
[
'
Movies
'
]:
if
not
'
Torrents
'
in
ptpmovie
:
continue
for
torrent
in
ptpmovie
[
'
Torrents
'
]:
if
not
self
.
torrent_meets_quality_spec
(
torrent
,
type
):
continue
torrentdesc
=
'
%s %s %s
'
%
(
torrent
[
'
Resolution
'
],
torrent
[
'
Source
'
],
torrent
[
'
Codec
'
])
if
'
GoldenPopcorn
'
in
torrent
and
torrent
[
'
GoldenPopcorn
'
]:
torrentdesc
+=
'
HQ
'
if
'
Scene
'
in
torrent
and
torrent
[
'
Scene
'
]:
torrentdesc
+=
'
Scene
'
if
'
RemasterTitle
'
in
torrent
and
torrent
[
'
RemasterTitle
'
]:
# eliminate odd characters...
torrentdesc
+=
self
.
htmltoascii
(
'
%s
'
)
new
=
{
'
id
'
:
int
(
torrent
[
'
Id
'
]),
'
type
'
:
'
torrent
'
,
'
name
'
:
re
.
sub
(
'
[^A-Za-z0-9\-_ ]+
'
,
''
,
'
%s - %s - %s
'
%
(
self
.
htmltoascii
(
ptpmovie
[
'
Title
'
]),
ptpmovie
[
'
Year
'
],
torrentdesc
)),
'
check_nzb
'
:
False
,
'
description
'
:
''
,
'
date
'
:
int
(
time
.
mktime
(
parse
(
torrent
[
'
UploadTime
'
]).
timetuple
())),
'
size
'
:
int
(
torrent
[
'
Size
'
])
/
(
1024
*
1024
),
'
provider
'
:
self
.
getName
(),
'
seeders
'
:
int
(
torrent
[
'
Seeders
'
]),
'
leechers
'
:
int
(
torrent
[
'
Leechers
'
]),
'
ptpobj
'
:
self
,
'
torrentjson
'
:
torrent
,
'
extra_score
'
:
(
lambda
torrent
:
(
50
if
torrent
[
'
torrentjson
'
][
'
GoldenPopcorn
'
]
else
0
)),
'
download
'
:
self
.
download
,
}
new
[
'
url
'
]
=
'
https://%s/torrents.php?action=download&id=%d
'
%
(
self
.
domain
,
new
[
'
id
'
])
new
[
'
score
'
]
=
fireEvent
(
'
score.calculate
'
,
new
,
movie
,
single
=
True
)
if
fireEvent
(
'
searcher.correct_movie
'
,
nzb
=
new
,
movie
=
movie
,
quality
=
quality
):
results
.
append
(
new
)
self
.
found
(
new
)
if
not
results
:
log
.
info
(
"
Found nothing for
'
%s
'"
%
movie
.
name
)
return
results
def
getMoreInfo
(
self
,
item
):
return
{}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment