Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
SiCKRAGE
sickrage
Commits
177461d8
Commit
177461d8
authored
Oct 17, 2017
by
echel0n
Browse files
Fixed NyaaTorrents provider
Refactored more provider code
parent
5563b946
Changes
35
Hide whitespace changes
Inline
Side-by-side
changelog.md
View file @
177461d8
# Changelog
-
*
46ee39d - 2017-10-17: Fixed attribute error for postprocessing queue
-
*
1602c2f - 2017-10-17: Fixed NyaaTorrents provider Refactored more provider code
-
*
5563b94 - 2017-10-17: Fixed attribute error for postprocessing queue
-
*
fea50e2 - 2017-10-17: Release v9.1.40
-
*
94e71c8 - 2017-10-17: Fixed issue #88 - Show are truncated when show set in different language
-
*
e6e0237 - 2017-10-17: Added Anizb Newznab provider
...
...
sickrage/clients/__init__.py
View file @
177461d8
...
...
@@ -318,7 +318,7 @@ class GenericClient(object):
try
:
# Sets per provider seed ratio
result
.
ratio
=
result
.
provider
.
seed_ratio
()
result
.
ratio
=
result
.
provider
.
seed_ratio
# lazy fix for now, I'm sure we already do this somewhere else too
result
=
self
.
_get_torrent_hash
(
result
)
...
...
sickrage/core/nameparser/__init__.py
View file @
177461d8
...
...
@@ -499,8 +499,8 @@ class NameParser(object):
final_result
.
quality
=
self
.
_combine_results
(
file_name_result
,
dir_name_result
,
'quality'
)
if
not
final_result
.
show
and
self
.
validate_show
:
raise
InvalidShowException
(
"Unable to match {} to a show in your database.
Parser result: {}"
.
format
(
name
,
str
(
final_result
))
)
raise
InvalidShowException
(
"Unable to match {result.original_name} to a show in your database. "
"
Parser result: {
result
}"
.
format
(
result
=
final_result
))
# if there's no useful info in it then raise an exception
if
final_result
.
season_number
is
None
and
not
final_result
.
episode_numbers
and
final_result
.
air_date
is
None
and
not
final_result
.
ab_episode_numbers
and
not
final_result
.
series_name
:
...
...
sickrage/providers/__init__.py
View file @
177461d8
...
...
@@ -88,6 +88,10 @@ class GenericProvider(object):
def
imageName
(
self
):
return
""
@
property
def
seed_ratio
(
self
):
return
''
def
_check_auth
(
self
):
return
True
...
...
@@ -534,13 +538,6 @@ class GenericProvider(object):
return
[
Proper
(
x
[
'name'
],
x
[
'url'
],
datetime
.
datetime
.
fromtimestamp
(
x
[
'time'
]),
self
.
show
)
for
x
in
results
]
def
seed_ratio
(
self
):
"""
Provider should override this value if custom seed ratio enabled
It should return the value of the provider seed ratio
"""
return
''
def
add_cookies_from_ui
(
self
):
"""
Adds the cookies configured from UI to the providers requests session
...
...
@@ -617,6 +614,14 @@ class TorrentProvider(GenericProvider):
return
self
.
id
+
'.png'
return
self
.
type
+
'.png'
@
property
def
seed_ratio
(
self
):
"""
Provider should override this value if custom seed ratio enabled
It should return the value of the provider seed ratio
"""
return
self
.
ratio
def
getResult
(
self
,
episodes
):
"""
Returns a result of the correct type for this provider
...
...
@@ -712,9 +717,6 @@ class TorrentProvider(GenericProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
@
classmethod
def
getProviders
(
cls
):
return
super
(
TorrentProvider
,
cls
).
loadProviders
(
cls
.
type
)
...
...
sickrage/providers/torrent/alpharatio.py
View file @
177461d8
...
...
@@ -31,7 +31,7 @@ class AlphaRatioProvider(TorrentProvider):
super
(
AlphaRatioProvider
,
self
).
__init__
(
"AlphaRatio"
,
'http://alpharatio.cc'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
...
...
@@ -139,7 +139,4 @@ class AlphaRatioProvider(TorrentProvider):
# Sort all the items by seeders if available
results
.
sort
(
key
=
lambda
k
:
try_int
(
k
.
get
(
'seeders'
,
0
)),
reverse
=
True
)
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
return
results
\ No newline at end of file
sickrage/providers/torrent/bitcannon.py
View file @
177461d8
...
...
@@ -33,15 +33,14 @@ class BitCannonProvider(TorrentProvider):
self
.
minseed
=
None
self
.
minleech
=
None
self
.
ratio
=
0
self
.
cache
=
TVCache
(
self
,
min_time
=
20
)
self
.
urls
.
update
({
'search'
:
'{base_url}/search/'
.
format
(
**
self
.
urls
),
'trackers'
:
'{base_url}/stats'
.
format
(
**
self
.
urls
),
})
self
.
cache
=
TVCache
(
self
,
min_time
=
20
)
def
search
(
self
,
search_strings
,
age
=
0
,
ep_obj
=
None
):
results
=
[]
...
...
@@ -104,5 +103,3 @@ class BitCannonProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/bitsoup.py
View file @
177461d8
...
...
@@ -39,7 +39,7 @@ class BitSoupProvider(TorrentProvider):
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
...
...
@@ -147,7 +147,4 @@ class BitSoupProvider(TorrentProvider):
# Sort all the items by seeders if available
results
.
sort
(
key
=
lambda
k
:
try_int
(
k
.
get
(
'seeders'
,
0
)),
reverse
=
True
)
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
return
results
\ No newline at end of file
sickrage/providers/torrent/btn.py
View file @
177461d8
...
...
@@ -40,10 +40,7 @@ class BTNProvider(TorrentProvider):
super
(
BTNProvider
,
self
).
__init__
(
"BTN"
,
'http://api.broadcasthe.net'
,
True
)
self
.
supports_absolute_numbering
=
True
self
.
api_key
=
None
self
.
ratio
=
None
self
.
reject_m2ts
=
False
self
.
cache
=
BTNCache
(
self
,
min_time
=
15
)
...
...
@@ -263,8 +260,6 @@ class BTNProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
class
BTNCache
(
tv_cache
.
TVCache
):
...
...
sickrage/providers/torrent/cpasbien.py
View file @
177461d8
...
...
@@ -28,7 +28,6 @@ class CpasbienProvider(TorrentProvider):
def
__init__
(
self
):
super
(
CpasbienProvider
,
self
).
__init__
(
"Cpasbien"
,
"http://www.cpasbien.io"
,
False
)
self
.
ratio
=
None
self
.
urls
.
update
({
'download'
:
'{base_url}/telechargement/%s'
.
format
(
**
self
.
urls
)
})
...
...
@@ -115,5 +114,3 @@ class CpasbienProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/gftracker.py
View file @
177461d8
...
...
@@ -33,18 +33,18 @@ class GFTrackerProvider(TorrentProvider):
def
__init__
(
self
):
super
(
GFTrackerProvider
,
self
).
__init__
(
"GFTracker"
,
'http://www.thegft.org'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
urls
.
update
({
'login'
:
'{base_url}/loginsite.php'
.
format
(
**
self
.
urls
),
'search'
:
'{base_url}/browse.php?view=%s%s'
.
format
(
**
self
.
urls
),
'download'
:
'{base_url}/%s'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
password
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
cookies
=
None
self
.
categories
=
"0&c26=1&c37=1&c19=1&c47=1&c17=1&c4=1&search="
...
...
@@ -165,6 +165,3 @@ class GFTrackerProvider(TorrentProvider):
results
.
sort
(
key
=
lambda
k
:
try_int
(
k
.
get
(
'seeders'
,
0
)),
reverse
=
True
)
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/hdbits.py
View file @
177461d8
...
...
@@ -31,18 +31,17 @@ class HDBitsProvider(TorrentProvider):
def
__init__
(
self
):
super
(
HDBitsProvider
,
self
).
__init__
(
"HDBits"
,
'https://hdbits.org'
,
True
)
self
.
username
=
None
self
.
passkey
=
None
self
.
ratio
=
None
self
.
cache
=
HDBitsCache
(
self
,
min_time
=
15
)
self
.
urls
.
update
({
'search'
:
'{base_url}/api/torrents'
.
format
(
**
self
.
urls
),
'rss'
:
'{base_url}/api/torrents'
.
format
(
**
self
.
urls
),
'download'
:
'{base_url}/download.php'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
passkey
=
None
self
.
cache
=
HDBitsCache
(
self
,
min_time
=
15
)
def
_check_auth
(
self
):
if
not
self
.
username
or
not
self
.
passkey
:
...
...
@@ -177,8 +176,6 @@ class HDBitsProvider(TorrentProvider):
return
json
.
dumps
(
post_data
)
def
seed_ratio
(
self
):
return
self
.
ratio
class
HDBitsCache
(
tv_cache
.
TVCache
):
...
...
sickrage/providers/torrent/hdspace.py
View file @
177461d8
...
...
@@ -35,26 +35,27 @@ class HDSpaceProvider(TorrentProvider):
def
__init__
(
self
):
super
(
HDSpaceProvider
,
self
).
__init__
(
"HDSpace"
,
'http://hd-space.org'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
cache
=
TVCache
(
self
,
min_time
=
10
)
self
.
urls
.
update
({
'login'
:
'{base_url}/index.php?page=login'
.
format
(
**
self
.
urls
),
'search'
:
'{base_url}/index.php?page=torrents&search=%s&active=1&options=0&category='
.
format
(
**
self
.
urls
),
'rss'
:
'{base_url}/rss_torrents.php?feed=dl'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
password
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
categories
=
[
15
,
21
,
22
,
24
,
25
,
40
]
# HDTV/DOC 1080/720, bluray, remux
for
cat
in
self
.
categories
:
self
.
urls
[
'search'
]
+=
str
(
cat
)
+
'%%3B'
self
.
urls
[
'rss'
]
+=
'&cat[]='
+
str
(
cat
)
self
.
urls
[
'search'
]
=
self
.
urls
[
'search'
][:
-
4
]
# remove extra %%3B
self
.
cache
=
TVCache
(
self
,
min_time
=
10
)
def
_check_auth
(
self
):
if
not
self
.
username
or
not
self
.
password
:
...
...
@@ -168,5 +169,3 @@ class HDSpaceProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/hdtorrents.py
View file @
177461d8
...
...
@@ -34,12 +34,6 @@ class HDTorrentsProvider(TorrentProvider):
def
__init__
(
self
):
super
(
HDTorrentsProvider
,
self
).
__init__
(
"HDTorrents"
,
'http://hd-torrents.org'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
urls
.
update
({
'login'
:
'{base_url}/login.php'
.
format
(
**
self
.
urls
),
'search'
:
'{base_url}/torrents.php?search=%s&active=1&options=0%s'
.
format
(
**
self
.
urls
),
...
...
@@ -47,6 +41,12 @@ class HDTorrentsProvider(TorrentProvider):
'home'
:
'{base_url}/%s'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
password
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
categories
=
"&category[]=59&category[]=60&category[]=30&category[]=38"
self
.
proper_strings
=
[
'PROPER'
,
'REPACK'
]
...
...
@@ -179,5 +179,3 @@ class HDTorrentsProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/hounddawgs.py
View file @
177461d8
...
...
@@ -30,19 +30,17 @@ class HoundDawgsProvider(TorrentProvider):
def
__init__
(
self
):
super
(
HoundDawgsProvider
,
self
).
__init__
(
"HoundDawgs"
,
'http://hounddawgs.org'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
cache
=
TVCache
(
self
,
min_time
=
20
)
self
.
urls
.
update
({
'search'
:
'{base_url}/torrents.php'
.
format
(
**
self
.
urls
),
'login'
:
'{base_url}/login.php'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
password
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
search_params
=
{
"filter_cat[85]"
:
1
,
"filter_cat[58]"
:
1
,
...
...
@@ -59,6 +57,8 @@ class HoundDawgsProvider(TorrentProvider):
"searchtags"
:
''
}
self
.
cache
=
TVCache
(
self
,
min_time
=
20
)
def
login
(
self
):
login_params
=
{
'username'
:
self
.
username
,
...
...
@@ -172,5 +172,3 @@ class HoundDawgsProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/iptorrents.py
View file @
177461d8
...
...
@@ -33,24 +33,24 @@ class IPTorrentsProvider(TorrentProvider):
def
__init__
(
self
):
super
(
IPTorrentsProvider
,
self
).
__init__
(
"IPTorrents"
,
'https://iptorrents.eu'
,
True
)
self
.
urls
.
update
({
'login'
:
'{base_url}/take_login.php'
.
format
(
**
self
.
urls
),
'search'
:
'{base_url}/t?%s%s&q=%s&qf=#torrents'
.
format
(
**
self
.
urls
)
})
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
freeleech
=
False
self
.
enable_cookies
=
True
self
.
minseed
=
None
self
.
minleech
=
None
self
.
enable_cookies
=
True
self
.
categories
=
'73=&60='
self
.
cache
=
TVCache
(
self
,
min_time
=
10
)
self
.
urls
.
update
({
'login'
:
'{base_url}/take_login.php'
.
format
(
**
self
.
urls
),
'search'
:
'{base_url}/t?%s%s&q=%s&qf=#torrents'
.
format
(
**
self
.
urls
)
})
self
.
categories
=
'73=&60='
def
_check_auth
(
self
):
if
not
self
.
username
or
not
self
.
password
:
raise
AuthException
(
"Your authentication credentials for "
+
self
.
name
+
" are missing, check your config."
)
...
...
@@ -175,5 +175,3 @@ class IPTorrentsProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/morethantv.py
View file @
177461d8
...
...
@@ -34,15 +34,6 @@ class MoreThanTVProvider(TorrentProvider):
def
__init__
(
self
):
super
(
MoreThanTVProvider
,
self
).
__init__
(
"MoreThanTV"
,
'http://www.morethan.tv'
,
True
)
self
.
_uid
=
None
self
.
_hash
=
None
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
# self.freeleech = False
self
.
urls
.
update
({
'login'
:
'{base_url}/login.php'
.
format
(
**
self
.
urls
),
'detail'
:
'{base_url}/torrents.php'
...
...
@@ -59,6 +50,14 @@ class MoreThanTVProvider(TorrentProvider):
'&id=%s'
.
format
(
**
self
.
urls
)
})
self
.
_uid
=
None
self
.
_hash
=
None
self
.
username
=
None
self
.
password
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
cookies
=
None
self
.
proper_strings
=
[
'PROPER'
,
'REPACK'
]
...
...
@@ -169,6 +168,3 @@ class MoreThanTVProvider(TorrentProvider):
results
.
sort
(
key
=
lambda
k
:
try_int
(
k
.
get
(
'seeders'
,
0
)),
reverse
=
True
)
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/nebulance.py
View file @
177461d8
...
...
@@ -27,12 +27,11 @@ from sickrage.providers import TorrentProvider
class
NebulanceProvider
(
TorrentProvider
):
def
__init__
(
self
):
super
(
NebulanceProvider
,
self
).
__init__
(
"Nebulance"
,
'http://nebulance.io'
,
True
)
self
.
username
=
None
self
.
password
=
None
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
...
...
@@ -152,5 +151,3 @@ class NebulanceProvider(TorrentProvider):
return
results
def
seed_ratio
(
self
):
return
self
.
ratio
sickrage/providers/torrent/nextorrent.py
View file @
177461d8
...
...
@@ -30,23 +30,19 @@ from sickrage.providers import TorrentProvider
class
NextorrentProvider
(
TorrentProvider
):
def
__init__
(
self
):
super
(
NextorrentProvider
,
self
).
__init__
(
"Nextorrent"
,
'http://nextorrent.pw'
,
False
)
self
.
urls
.
update
({
'series'
:
'{base_url}/torrents/series'
.
format
(
**
self
.
urls
)
})
self
.
confirmed
=
True
self
.
ratio
=
None
self
.
minseed
=
None
self
.
minleech
=
None
self
.
cache
=
TVCache
(
self
,
min_time
=
15
)
self
.
urls
.
update
({
'series'
:
'{base_url}/torrents/series'
.
format
(
**
self
.
urls
)
})
def
seed_ratio
(
self
):
return
self
.
ratio
def
get_download_url
(
self
,
url
):
try
:
data
=
sickrage
.
srCore
.
srWebSession
.
get
(
urljoin
(
self
.
urls
[
'base_url'
],
url
)).
text
...
...
sickrage/providers/torrent/nyaatorrents.py
View file @
177461d8
...
...
@@ -18,9 +18,6 @@
from
__future__
import
unicode_literals
import
re
import
urllib
import
sickrage
from
sickrage.core.caches.tv_cache
import
TVCache
from
sickrage.core.helpers
import
convert_size
,
try_int
...
...
@@ -33,76 +30,104 @@ class NyaaProvider(TorrentProvider):
self
.
supports_absolute_numbering
=
True
self
.
anime_only
=
True
self
.
ratio
=
None
self
.
cache
=
TVCache
(
self
,
min_time
=
15
)
self
.
minseed
=
0
self
.
minleech
=
0
self
.
confirmed
=
False
self
.
cache
=
TVCache
(
self
,
min_time
=
20
)
def
search
(
self
,
search_strings
,
age
=
0
,
ep_obj
=
None
):
"""
Search a provider and parse the results.
:param search_strings: A dict with mode (key) and the search value (value)
:param age: Not used
:param ep_obj: Not used
:returns: A list of search results (structure)
"""
results
=
[]
if
self
.
show
and
not
self
.
show
.
is_anime
:
return
results
# Search Params
search_params
=
{
'page'
:
'rss'
,
'c'
:
'1_0'
,
# All Anime
'f'
:
0
,
# No filter
'q'
:
''
,
}
for
mode
in
search_strings
:
sickrage
.
srCore
.
srLogger
.
debug
(
'Search mode: {}'
.
format
(
mode
))
if
self
.
confirmed
:
search_params
[
'f'
]
=
2
# Trusted only
sickrage
.
srCore
.
srLogger
.
debug
(
'Searching only confirmed torrents'
)
for
mode
in
search_strings
.
keys
():
sickrage
.
srCore
.
srLogger
.
debug
(
"Search Mode: %s"
%
mode
)
for
search_string
in
search_strings
[
mode
]:
if
mode
!=
'RSS'
:
sickrage
.
srCore
.
srLogger
.
debug
(
"Search string: %s"
%
search_string
)
params
=
{
"page"
:
'rss'
,
"cats"
:
'1_0'
,
# All anime
"sort"
:
2
,
# Sort Descending By Seeders
"order"
:
1
}
if
mode
!=
'RSS'
:
params
[
"term"
]
=
search_string
.
encode
(
'utf-8'
)
sickrage
.
srCore
.
srLogger
.
debug
(
'Search string: {}'
.
format
(
search_string
))
search_params
[
'q'
]
=
search_string
searchURL
=
self
.
urls
[
'base_url'
]
+
'?'
+
urllib
.
urlencode
(
params
)
sickrage
.
srCore
.
srLogger
.
debug
(
"Search URL: %s"
%
searchURL
)
data
=
self
.
cache
.
getRSSFeed
(
self
.
urls
[
'base_url'
],
params
=
search_params
)
if
not
data
:
sickrage
.
srCore
.
srLogger
.
debug
(
'No data returned from provider'
)
continue
if
not
data
.
get
(
'entries'
):
sickrage
.
srCore
.
srLogger
.
debug
(
'Data returned from provider does not contain any {0}torrents'
,
'confirmed '
if
self
.
confirmed
else
''
)
continue
summary_regex
=
ur
"(\d+) seeder\(s\), (\d+) leecher\(s\), \d+ download\(s\) - (\d+.?\d* [KMGT]iB)(.*)"
s
=
re
.
compile
(
summary_regex
,
re
.
DOTALL
)
results
+=
self
.
parse
(
data
[
'entries'
],
mode
)
results
=
[]
for
curItem
in
self
.
cache
.
getRSSFeed
(
searchURL
)[
'entries'
]
or
[]:
title
=
curItem
[
'title'
]
download_url
=
curItem
[
'link'
]
if
not
all
([
title
,
download_url
]):
continue
# Sort all the items by seeders if available
results
.
sort
(
key
=
lambda
k
:
try_int
(
k
.
get
(
'seeders'
,
0
)),
reverse
=
True
)
seeders
,
leechers
,
size
,
verified
=
s
.
findall
(
curItem
[
'summary'
])[
0
]
size
=
convert_size
(
size
,
-
1
)
return
results
# Filter unseeded torrent
if
seeders
<
self
.
minseed
or
leechers
<
self
.
minleech
:
if
mode
!=
'RSS'
:
sickrage
.
srCore
.
srLogger
.
debug
(
"Discarding torrent because it doesn't meet the minimum seeders or leechers: {} (S:{} L:{})"
.
format
(
title
,
seeders
,
leechers
))
continue
def
parse
(
self
,
data
,
mode
):
"""
Parse search results for items.
if
self
.
confirmed
and
not
verified
and
mode
!=
'RSS'
:
sickrage
.
srCore
.
srLogger
.
debug
(
"Found result "
+
title
+
" but that doesn't seem like a verified result so I'm ignoring it"
)
continue
:param data: The raw response from a search
:param mode: The current mode used to search, e.g. RSS
item
=
{
'title'
:
title
,
'link'
:
download_url
,
'size'
:
size
,
'seeders'
:
seeders
,
'leechers'
:
leechers
,
'hash'
:
''
}
:return: A list of items found
"""
if
mode
!=
'RSS'
:
sickrage
.
srCore
.
srLogger
.
debug
(
"Found result: {}"
.
format
(
title
))
results
=
[]
results
.
append
(
item
)