├── .gitignore ├── LICENSE ├── README.md ├── addon.xml ├── changelog.txt ├── credits.txt ├── icon.png ├── lib ├── __init__.py ├── default.py └── openscrapers │ ├── __init__.py │ ├── modules │ ├── __init__.py │ ├── anilist.py │ ├── cache.py │ ├── cfdecoder.py │ ├── cfscrape.py │ ├── cleandate.py │ ├── cleantitle.py │ ├── client.py │ ├── control.py │ ├── debrid.py │ ├── directstream.py │ ├── dom_parser.py │ ├── dom_parser2.py │ ├── js2py │ │ ├── __init__.py │ │ ├── base.py │ │ ├── constructors │ │ │ ├── __init__.py │ │ │ ├── jsarray.py │ │ │ ├── jsboolean.py │ │ │ ├── jsdate.py │ │ │ ├── jsfunction.py │ │ │ ├── jsmath.py │ │ │ ├── jsnumber.py │ │ │ ├── jsobject.py │ │ │ ├── jsregexp.py │ │ │ ├── jsstring.py │ │ │ ├── six.py │ │ │ └── time_helpers.py │ │ ├── evaljs.py │ │ ├── host │ │ │ ├── __init__.py │ │ │ ├── console.py │ │ │ ├── dom │ │ │ │ ├── __init__.py │ │ │ │ ├── constants.py │ │ │ │ └── interface.py │ │ │ ├── jseval.py │ │ │ └── jsfunctions.py │ │ ├── legecy_translators │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ ├── exps.py │ │ │ ├── flow.py │ │ │ ├── functions.py │ │ │ ├── jsparser.py │ │ │ ├── nodevisitor.py │ │ │ ├── nparser.py │ │ │ ├── objects.py │ │ │ ├── tokenize.py │ │ │ ├── translator.py │ │ │ └── utils.py │ │ ├── prototypes │ │ │ ├── __init__.py │ │ │ ├── jsarray.py │ │ │ ├── jsboolean.py │ │ │ ├── jserror.py │ │ │ ├── jsfunction.py │ │ │ ├── jsjson.py │ │ │ ├── jsnumber.py │ │ │ ├── jsobject.py │ │ │ ├── jsregexp.py │ │ │ ├── jsstring.py │ │ │ └── six.py │ │ ├── pyjs.py │ │ ├── six.py │ │ ├── todo │ │ ├── translators │ │ │ ├── __init__.py │ │ │ ├── friendly_nodes.py │ │ │ ├── jsregexps.py │ │ │ ├── markdown.js │ │ │ ├── pyjsparser.py │ │ │ ├── pyjsparserdata.py │ │ │ ├── six.py │ │ │ ├── std_nodes.py │ │ │ ├── translating_nodes.py │ │ │ └── translator.py │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── definitions.py │ │ │ ├── injector.py │ │ │ └── six.py │ ├── jsunfuck.py │ ├── jsunpack.py │ ├── log_utils.py │ ├── proxy.py │ ├── pyaes │ │ ├── __init__.py │ │ ├── aes.py │ │ ├── blockfeeder.py │ │ └── util.py │ ├── regex.py │ ├── source_utils.py │ ├── trakt.py │ ├── tvmaze.py │ ├── utils.py │ └── workers.py │ └── sources_openscrapers │ ├── __init__.py │ ├── de │ ├── allucde.py │ ├── animebase.py │ ├── animeloads.py │ ├── bs.py │ ├── cine.py │ ├── cinenator.py │ ├── ddl.py │ ├── filmpalast.py │ ├── foxx.py │ ├── hdfilme.py │ ├── hdstreams.py │ ├── horrorkino.py │ ├── iload.py │ ├── kinodogs.py │ ├── kinoking.py │ ├── kinow.py │ ├── kinox.py │ ├── lichtspielhaus.py │ ├── movie2k-ac.py │ ├── movie2k-ag.py │ ├── movie2z.py │ ├── movie4k.py │ ├── moviesever.py │ ├── movietown.py │ ├── netzkino.py │ ├── proxer.py │ ├── pureanime.py │ ├── serienstream.py │ ├── seriesever.py │ ├── stream-to.py │ ├── streamdream.py │ ├── streamflix.py │ ├── streamit.py │ ├── tata.py │ ├── video4k.py │ └── view4u.py │ ├── en │ ├── 0123putlocker.py │ ├── 123fox.py │ ├── 123hbo.py │ ├── 123hulu.py │ ├── 123movieshubz.py │ ├── 300mbdownload.py │ ├── 4kmovieto.py │ ├── Hdmto.py │ ├── animetoon.py │ ├── azmovie.py │ ├── bnwmovies.py │ ├── cartoonhd.py │ ├── cmovieshd.py │ ├── cmovieshdbz.py │ ├── coolmoviezone.py │ ├── downflix.py │ ├── extramovies.py │ ├── filmxy.py │ ├── fmovies.py │ ├── freefmovies.py │ ├── freeputlockers.py │ ├── furk.py │ ├── gostream.py │ ├── gowatchseries.py │ ├── hdpopcorns.py │ ├── iwaatch.py │ ├── kattv.py │ ├── l23movies.py │ ├── library.py │ ├── moviesonline.py │ ├── movietoken.py │ ├── myprojectfreetv.py │ ├── odb.py │ ├── openloadmovie.py │ ├── ororo.py │ ├── plocker.py │ ├── primewire.py │ ├── putlocker.py │ ├── reddit.py │ ├── seehd.py │ ├── series9.py │ ├── seriesfree.py │ ├── seriesonline.py │ ├── sezonlukdizi.py │ ├── solarmoviez.py │ ├── tvbox.py │ ├── vdonip.py │ ├── videoscraper.py │ ├── vidics.py │ ├── watchseries.py │ ├── xwatchseries.py │ └── ymovies.py │ ├── en_DebridOnly │ ├── 300mbfilms.py │ ├── bestmoviez.py │ ├── ddlspot.py │ ├── ddlvalley.py │ ├── directdl.py │ ├── invictus.py │ ├── iwantmyshow.py │ ├── moviesleak.py │ ├── myvideolink.py │ ├── playmovies.py │ ├── rlsbb.py │ ├── scenerls.py │ ├── scnsrc.py │ ├── ultrahdindir.py │ └── wrzcraft.py │ ├── en_Torrent │ ├── bitlord.py │ ├── eztv.py │ ├── glodls.py │ ├── kickass2.py │ ├── limetorrents.py │ ├── piratebay.py │ ├── torrentapi.py │ ├── torrentdownloads.py │ ├── yify.py │ └── zoogle.py │ ├── es │ ├── megapelistv.py │ ├── peliculasdk.py │ ├── pelisplustv.py │ ├── pepecine.py │ └── seriespapaya.py │ ├── gr │ ├── gamatotv.py │ ├── liomenoi.py │ ├── tainiesonline.py │ ├── tainiomania.py │ └── xrysoi.py │ └── pl │ ├── alltube.py │ ├── boxfilm.py │ ├── cdahd.py │ ├── cdax.py │ ├── ekinomaniak.py │ ├── ekinotv.py │ ├── filiser.py │ ├── filmwebbooster.py │ ├── iitv.py │ ├── movieneo.py │ ├── openkatalog.py │ ├── paczamy.py │ ├── segos.py │ ├── szukajkatv.py │ └── trt.py ├── resources └── settings.xml └── scrape-test.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # IPython 79 | profile_default/ 80 | ipython_config.py 81 | 82 | # pyenv 83 | .python-version 84 | 85 | # celery beat schedule file 86 | celerybeat-schedule 87 | 88 | # SageMath parsed files 89 | *.sage.py 90 | 91 | # Environments 92 | .env 93 | .venv 94 | env/ 95 | venv/ 96 | ENV/ 97 | env.bak/ 98 | venv.bak/ 99 | 100 | # Spyder project settings 101 | .spyderproject 102 | .spyproject 103 | 104 | # Rope project settings 105 | .ropeproject 106 | 107 | # mkdocs documentation 108 | /site 109 | 110 | # mypy 111 | .mypy_cache/ 112 | .dmypy.json 113 | dmypy.json 114 | 115 | # Pyre type checker 116 | .pyre/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | # ██████╗ ██████╗ ███████╗███╗ ██╗ 3 | # ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ 4 | # ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ 5 | # ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ 6 | # ╚██████╔╝██║ ███████╗██║ ╚████║ 7 | # ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ 8 | # 9 | # ███████╗ ██████╗██████╗ █████╗ ██████╗ ███████╗██████╗ ███████╗ 10 | # ██╔════╝██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗██╔════╝ 11 | # ███████╗██║ ██████╔╝███████║██████╔╝█████╗ ██████╔╝███████╗ 12 | # ╚════██║██║ ██╔══██╗██╔══██║██╔═══╝ ██╔══╝ ██╔══██╗╚════██║ 13 | # ███████║╚██████╗██║ ██║██║ ██║██║ ███████╗██║ ██║███████║ 14 | # ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ 15 | # 16 | ``` 17 | 18 | Welcome to OpenScrapers Project, 19 | 20 | This project is in hopes to unify the community and contribute to one scraper pack for multi scraper add-ons and not 21 | having the repo go dead or disappear. The goal is to stop the drama, the egos, everything and work together and make 22 | this a great scraper pack so the community can benefit. Addons4Kodi takes no credit for putting this together, and we 23 | thank all devs that have contributed to multiple projects over time. 24 | 25 | # OpenScrapers Repo 26 | 27 | You can add the source directory to your own repository for convenience and updates 28 | ``` 29 | 30 | https://raw.githubusercontent.com/a4k-openproject/repository.openscrapers/master/zips/addons.xml 31 | https://raw.githubusercontent.com/a4k-openproject/repository.openscrapers/master/zips/addons.xml.md5 32 | https://raw.githubusercontent.com/a4k-openproject/repository.openscrapers/master/zips/ 33 | 34 | ``` 35 | # How to Import Open Scrapers Into Any Addon 36 | 37 | Any multi-source Kodi addon can be altered to use these new scrapers instead of its own, you can follow the 38 | instructions below to get things updated. When appling to a different addon, change "name_of_addon" with the name 39 | of the addon. 40 | 41 | Open the `addons/plugin.video.name_of_addon/addon.xml`. 42 | 43 | Add the following line to the addon.xml file: 44 | 45 | `` 46 | 47 | Open addons/script.module.name_of_addon/lib/resources/lib/modules/sources.py 48 | 49 | Add the following line to the `sources.py` file: 50 | 51 | `import openscrapers` 52 | 53 | Add it right after the line that says: 54 | 55 | `from resources.lib.modules import thexem` 56 | 57 | You will also need to change a few lines in the def `getConstants(self)` function in `sources.py` file: 58 | 59 | Find the line that says: 60 | 61 | `from resources.lib.sources import sources` 62 | 63 | Comment out that line by adding a pound/hashtag at the beginning like this: 64 | 65 | `#from resources.lib.sources import sources` 66 | 67 | add the following: 68 | 69 | `from openscrapers import sources` 70 | -------------------------------------------------------------------------------- /addon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | executable 10 | 11 | 12 | all 13 | OpenScrapers Module 14 | Scrape common video host for URL's to be playable in Kodi, simplifying addon development of video plugins requiring multi video hosts. 15 | The author is not responsible for the use of this addon. The author is not responsible for the content found using this addon. The author does not host or own any content found within this addon.[CR]The author is in no way affiliated with Kodi, Team Kodi, or the XBMC Foundation.[CR]This is a Non-profit resource, organized solely for educational purposes which is protected under the Fair-Use doctrine of the Copyright Act, Specifically section 107, which does promote freedom of expression, by permitting the unlicensed use of copyright-protected works. 16 | all 17 | GNU GENERAL PUBLIC LICENSE. Version 3, 29 June 2007 18 | 19 | icon.png 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | OpenScrapers Module Changelog: 2 | 0.0.0.3 3 | - Label changes 4 | 5 | 0.0.0.2 6 | - Documentation updates 7 | 8 | 0.0.0.1 9 | - Initial commit 10 | -------------------------------------------------------------------------------- /credits.txt: -------------------------------------------------------------------------------- 1 | This is a new Project to try and unify MultiScraper forks scrapers all into one pack. This is based on projects from those listed below. I respect everything they've done for the scene and they all deserve their credit for their work in whatever capacity they have contributed. I thank everyone and i hope that everyone can help the community have a unified scraper pack, with no more drama :) 2 | 3 | - Lambda 4 | - TKNorris 5 | - Mr.Blamo 6 | - Nixgates 7 | - I-A-C 8 | - WilsonMagic 9 | - 13Clowns 10 | - Eggman 11 | - Jor-El 12 | - Maud'Dib 13 | - Jewbmx 14 | - Team Supremacy 15 | - Team Colossus 16 | - Team Universal 17 | - and any others i may have missed! 18 | 19 | Note: Any scraper with credit removed is at the request of the dev that made it, all credit was left intact 20 | Based On: Civitas Scrapers/LambdaScrapers 21 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/I-A-C/script.module.openscrapers/3bd73e93339cc2f2e5df0570aaa145dc8d5550b7/icon.png -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/I-A-C/script.module.openscrapers/3bd73e93339cc2f2e5df0570aaa145dc8d5550b7/lib/__init__.py -------------------------------------------------------------------------------- /lib/openscrapers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | import pkgutil 4 | import os.path 5 | 6 | try: 7 | import xbmcaddon 8 | __addon__ = xbmcaddon.Addon(id='script.module.openscrapers') 9 | except: 10 | __addon__ = None 11 | pass 12 | 13 | def sources(): 14 | try: 15 | sourceDict = [] 16 | if __addon__ is not None: 17 | provider = __addon__.getSetting('module.provider') 18 | else: 19 | provider = 'openscrapers' 20 | sourceFolder = getScraperFolder(provider) 21 | sourceFolderLocation = os.path.join(os.path.dirname(__file__), sourceFolder) 22 | sourceSubFolders = [x[1] for x in os.walk(sourceFolderLocation)][0] 23 | for i in sourceSubFolders: 24 | for loader, module_name, is_pkg in pkgutil.walk_packages([os.path.join(sourceFolderLocation, i)]): 25 | if is_pkg: 26 | continue 27 | try: 28 | module = loader.find_module(module_name).load_module(module_name) 29 | sourceDict.append((module_name, module.source())) 30 | except: 31 | pass 32 | return enabledHosters(sourceDict) 33 | except: 34 | return [] 35 | 36 | def enabledHosters(sourceDict, function=False): 37 | if __addon__ is not None: 38 | enabledHosts = [i[0] for i in sourceDict if __addon__.getSetting('provider.' + i[0].split('_')[0]) == 'true'] 39 | returnedHosts = [i for i in sourceDict if i[0] in enabledHosts] 40 | else: 41 | return sourceDict 42 | return returnedHosts 43 | 44 | def providerSources(): 45 | sourceSubFolders = [x[1] for x in os.walk(os.path.dirname(__file__))][0] 46 | return getModuleName(sourceSubFolders) 47 | 48 | def providerNames(): 49 | providerList = [] 50 | provider = __addon__.getSetting('module.provider') 51 | sourceFolder = getScraperFolder(provider) 52 | sourceFolderLocation = os.path.join(os.path.dirname(__file__), sourceFolder) 53 | sourceSubFolders = [x[1] for x in os.walk(sourceFolderLocation)][0] 54 | for i in sourceSubFolders: 55 | for loader, module_name, is_pkg in pkgutil.walk_packages([os.path.join(sourceFolderLocation, i)]): 56 | if is_pkg: 57 | continue 58 | correctName = module_name.split('_')[0] 59 | providerList.append(correctName) 60 | return providerList 61 | 62 | def getAllHosters(): 63 | def _sources(sourceFolder, appendList): 64 | sourceFolderLocation = os.path.join(os.path.dirname(__file__), sourceFolder) 65 | sourceSubFolders = [x[1] for x in os.walk(sourceFolderLocation)][0] 66 | for i in sourceSubFolders: 67 | for loader, module_name, is_pkg in pkgutil.walk_packages([os.path.join(sourceFolderLocation, i)]): 68 | if is_pkg: 69 | continue 70 | try: mn = str(module_name).split('_')[0] 71 | except: mn = str(module_name) 72 | appendList.append(mn) 73 | sourceSubFolders = [x[1] for x in os.walk(os.path.dirname(__file__))][0] 74 | appendList = [] 75 | for item in sourceSubFolders: 76 | if item != 'modules': 77 | _sources(item, appendList) 78 | return list(set(appendList)) 79 | 80 | def getScraperFolder(scraper_source): 81 | sourceSubFolders = [x[1] for x in os.walk(os.path.dirname(__file__))][0] 82 | return [i for i in sourceSubFolders if scraper_source.lower() in i.lower()][0] 83 | 84 | def getModuleName(scraper_folders): 85 | nameList = [] 86 | for s in scraper_folders: 87 | try: nameList.append(s.split('_')[1].lower().title()) 88 | except: pass 89 | return nameList 90 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/anilist.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | import urlparse, urllib 23 | 24 | from resources.lib.modules import cache 25 | from resources.lib.modules import client 26 | from resources.lib.modules import cleantitle 27 | from resources.lib.modules import utils 28 | 29 | 30 | def _getAniList(url): 31 | try: 32 | url = urlparse.urljoin('https://anilist.co', '/api%s' % url) 33 | return client.request(url, headers={'Authorization': '%s %s' % cache.get(_getToken, 1), 'Content-Type': 'application/x-www-form-urlencoded'}) 34 | except: 35 | pass 36 | 37 | 38 | def _getToken(): 39 | result = urllib.urlencode({'grant_type': 'client_credentials', 'client_id': 'kodiexodus-7erse', 'client_secret': 'XelwkDEccpHX2uO8NpqIjVf6zeg'}) 40 | result = client.request('https://anilist.co/api/auth/access_token', post=result, headers={'Content-Type': 'application/x-www-form-urlencoded'}, error=True) 41 | result = utils.json_loads_as_str(result) 42 | return result['token_type'], result['access_token'] 43 | 44 | 45 | def getAlternativTitle(title): 46 | try: 47 | t = cleantitle.get(title) 48 | 49 | r = _getAniList('/anime/search/%s' % title) 50 | r = [(i.get('title_romaji'), i.get('synonyms', [])) for i in utils.json_loads_as_str(r) if cleantitle.get(i.get('title_english', '')) == t] 51 | r = [i[1][0] if i[0] == title and len(i[1]) > 0 else i[0] for i in r] 52 | r = [i for i in r if i if i != title][0] 53 | return r 54 | except: 55 | pass 56 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/cleandate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | 23 | import datetime 24 | import time 25 | 26 | 27 | def iso_2_utc(iso_ts): 28 | if not iso_ts or iso_ts is None: 29 | return 0 30 | 31 | delim = -1 32 | 33 | if not iso_ts.endswith('Z'): 34 | delim = iso_ts.rfind('+') 35 | if delim == -1: 36 | delim = iso_ts.rfind('-') 37 | 38 | if delim > -1: 39 | ts = iso_ts[:delim] 40 | sign = iso_ts[delim] 41 | tz = iso_ts[delim + 1:] 42 | else: 43 | ts = iso_ts 44 | tz = None 45 | 46 | if ts.find('.') > -1: 47 | ts = ts[:ts.find('.')] 48 | 49 | try: 50 | d = datetime.datetime.strptime(ts, '%Y-%m-%dT%H:%M:%S') 51 | except TypeError: 52 | d = datetime.datetime(*(time.strptime(ts, '%Y-%m-%dT%H:%M:%S')[0:6])) 53 | 54 | dif = datetime.timedelta() 55 | if tz: 56 | hours, minutes = tz.split(':') 57 | hours = int(hours) 58 | minutes = int(minutes) 59 | if sign == '-': 60 | hours = -hours 61 | minutes = -minutes 62 | dif = datetime.timedelta(minutes=minutes, hours=hours) 63 | utc_dt = d - dif 64 | epoch = datetime.datetime.utcfromtimestamp(0) 65 | delta = utc_dt - epoch 66 | 67 | try: 68 | seconds = delta.total_seconds() # works only on 2.7 69 | except: 70 | seconds = delta.seconds + delta.days * 24 * 3600 # close enough 71 | 72 | return seconds 73 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/cleantitle.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | import re 23 | import unicodedata 24 | 25 | 26 | def get(title): 27 | if title is None: 28 | return 29 | try: 30 | title = title.encode('utf-8') 31 | except: 32 | pass 33 | title = str(title) 34 | title = re.sub('&#(\d);', '', title) 35 | title = re.sub('(&#[0-9]+)([^;^0-9]+)', '\\1;\\2', title) 36 | title = title.replace('"', '\"').replace('&', '&') 37 | title = re.sub('\n|([[].+?[]])|([(].+?[)])|\s(vs|v[.])\s|(:|;|-|"|,|\'|_|\.|\?)|\s', '', title) 38 | return title.lower() 39 | 40 | 41 | def geturl(title): 42 | if title is None: 43 | return 44 | title = title.lower() 45 | title = title.translate(None, ':*?"\'\.<>|&!,') 46 | title = title.replace('/', '-') 47 | title = title.replace(' ', '-') 48 | title = title.replace('--', '-') 49 | return title 50 | 51 | 52 | def get_simple(title): 53 | if title is None: 54 | return 55 | title = title.lower() 56 | title = re.sub('(\d{4})', '', title) 57 | title = re.sub('&#(\d+);', '', title) 58 | title = re.sub('(&#[0-9]+)([^;^0-9]+)', '\\1;\\2', title) 59 | title = title.replace('"', '\"').replace('&', '&') 60 | title = re.sub('\n|\(|\)|\[|\]|\{|\}|\s(vs|v[.])\s|(:|;|-|–|"|,|\'|_|\.|\?)|\s', '', title).lower() 61 | return title 62 | 63 | 64 | def getsearch(title): 65 | if title is None: 66 | return 67 | title = title.lower() 68 | title = re.sub('&#(\d+);', '', title) 69 | title = re.sub('(&#[0-9]+)([^;^0-9]+)', '\\1;\\2', title) 70 | title = title.replace('"', '\"').replace('&', '&') 71 | title = re.sub('\\\|/|-|–|:|;|\*|\?|"|\'|<|>|\|', '', title).lower() 72 | return title 73 | 74 | 75 | def query(title): 76 | if title is None: 77 | return 78 | title = title.replace('\'', '').rsplit(':', 1)[0].rsplit(' -', 1)[0].replace('-', ' ') 79 | return title 80 | 81 | 82 | def normalize(title): 83 | try: 84 | try: 85 | return title.decode('ascii').encode("utf-8") 86 | except: 87 | pass 88 | 89 | return str(''.join(c for c in unicodedata.normalize('NFKD', unicode(title.decode('utf-8'))) if 90 | unicodedata.category(c) != 'Mn')) 91 | except: 92 | return title 93 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/debrid.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | from openscrapers.modules import log_utils 23 | from openscrapers.modules import control 24 | 25 | try: 26 | import resolveurl 27 | 28 | debrid_resolvers = [resolver() for resolver in resolveurl.relevant_resolvers(order_matters=True) if resolver.isUniversal()] 29 | 30 | if len(debrid_resolvers) == 0: 31 | # Support Rapidgator accounts! Unfortunately, `sources.py` assumes that rapidgator.net is only ever 32 | # accessed via a debrid service, so we add rapidgator as a debrid resolver and everything just works. 33 | # As a bonus(?), rapidgator links will be highlighted just like actual debrid links 34 | debrid_resolvers = [resolver() for resolver in resolveurl.relevant_resolvers(order_matters=True,include_universal=False) if 'rapidgator.net' in resolver.domains] 35 | 36 | except: 37 | debrid_resolvers = [] 38 | 39 | 40 | def status(torrent=False): 41 | debrid_check = debrid_resolvers != [] 42 | if debrid_check is True: 43 | if torrent: 44 | enabled = control.setting('torrent.enabled') 45 | if enabled == '' or enabled.lower() == 'true': 46 | return True 47 | else: 48 | return False 49 | return debrid_check 50 | 51 | def resolver(url, debrid): 52 | try: 53 | debrid_resolver = [resolver for resolver in debrid_resolvers if resolver.name == debrid][0] 54 | 55 | debrid_resolver.login() 56 | _host, _media_id = debrid_resolver.get_host_and_id(url) 57 | stream_url = debrid_resolver.get_media_url(_host, _media_id) 58 | 59 | return stream_url 60 | except Exception as e: 61 | log_utils.log('%s Resolve Failure: %s' % (debrid, e), log_utils.LOGWARNING) 62 | return None 63 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/__init__.py: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | # 3 | # Copyright 2014, 2015 Piotr Dabkowski 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 'Software'), 7 | # to deal in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | # the Software, and to permit persons to whom the Software is furnished to do so, subject 10 | # to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all copies or 13 | # substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 16 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 20 | 21 | """ This module allows you to translate and execute Javascript in pure python. 22 | Basically its implementation of ECMAScript 5.1 in pure python. 23 | 24 | Use eval_js method to execute javascript code and get resulting python object (builtin if possible). 25 | 26 | EXAMPLE: 27 | >>> import js2py 28 | >>> add = js2py.eval_js('function add(a, b) {return a + b}') 29 | >>> add(1, 2) + 3 30 | 6 31 | >>> add('1', 2, 3) 32 | u'12' 33 | >>> add.constructor 34 | function Function() { [python code] } 35 | 36 | 37 | Or use EvalJs to execute many javascript code fragments under same context - you would be able to get any 38 | variable from the context! 39 | 40 | >>> js = js2py.EvalJs() 41 | >>> js.execute('var a = 10; function f(x) {return x*x};') 42 | >>> js.f(9) 43 | 81 44 | >>> js.a 45 | 10 46 | 47 | Also you can use its console method to play with interactive javascript console. 48 | 49 | 50 | Use parse_js to parse (syntax tree is just like in esprima.js) and translate_js to trasnlate JavaScript. 51 | 52 | Finally, you can use pyimport statement from inside JS code to import and use python libraries. 53 | 54 | >>> js2py.eval_js('pyimport urllib; urllib.urlopen("https://www.google.com")') 55 | 56 | NOTE: This module is still not fully finished: 57 | 58 | Date and JSON builtin objects are not implemented 59 | Array prototype is not fully finished (will be soon) 60 | 61 | Other than that everything should work fine. 62 | 63 | """ 64 | 65 | __author__ = 'Piotr Dabkowski' 66 | __all__ = ['EvalJs', 'translate_js', 'import_js', 'eval_js', 'parse_js', 'translate_file', 'run_file'] 67 | from .evaljs import * 68 | from .translators import parse as parse_js 69 | 70 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Piotr Dabkowski' -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsarray.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | 3 | @Js 4 | def Array(): 5 | if len(arguments)==0 or len(arguments)>1: 6 | return arguments.to_list() 7 | a = arguments[0] 8 | if isinstance(a, PyJsNumber): 9 | length = a.to_uint32() 10 | if length!=a.value: 11 | raise MakeError('RangeError', 'Invalid array length') 12 | temp = Js([]) 13 | temp.put('length', a) 14 | return temp 15 | return [a] 16 | 17 | Array.create = Array 18 | Array.own['length']['value'] = Js(1) 19 | 20 | @Js 21 | def isArray(arg): 22 | return arg.Class=='Array' 23 | 24 | 25 | Array.define_own_property('isArray', {'value': isArray, 26 | 'enumerable': False, 27 | 'writable': True, 28 | 'configurable': True}) 29 | 30 | Array.define_own_property('prototype', {'value': ArrayPrototype, 31 | 'enumerable': False, 32 | 'writable': False, 33 | 'configurable': False}) 34 | 35 | ArrayPrototype.define_own_property('constructor', {'value': Array, 36 | 'enumerable': False, 37 | 'writable': True, 38 | 'configurable': True}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsboolean.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | 3 | BooleanPrototype.define_own_property('constructor', {'value': Boolean, 4 | 'enumerable': False, 5 | 'writable': True, 6 | 'configurable': True}) 7 | 8 | Boolean.define_own_property('prototype', {'value': BooleanPrototype, 9 | 'enumerable': False, 10 | 'writable': False, 11 | 'configurable': False}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsfunction.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | try: 3 | from ..translators.translator import translate_js 4 | except: 5 | pass 6 | 7 | 8 | @Js 9 | def Function(): 10 | # convert arguments to python list of strings 11 | a = [e.to_string().value for e in arguments.to_list()] 12 | body = ';' 13 | args = () 14 | if len(a): 15 | body = '%s;' % a[-1] 16 | args = a[:-1] 17 | # translate this function to js inline function 18 | js_func = '(function (%s) {%s})' % (','.join(args), body) 19 | # now translate js inline to python function 20 | py_func = translate_js(js_func, '') 21 | # add set func scope to global scope 22 | # a but messy solution but works :) 23 | globals()['var'] = PyJs.GlobalObject 24 | # define py function and return it 25 | temp = executor(py_func, globals()) 26 | temp.source = '{%s}'%body 27 | temp.func_name = 'anonymous' 28 | return temp 29 | 30 | def executor(f, glob): 31 | exec(f, globals()) 32 | return globals()['PyJs_anonymous_0_'] 33 | 34 | 35 | #new statement simply calls Function 36 | Function.create = Function 37 | 38 | #set constructor property inside FunctionPrototype 39 | 40 | fill_in_props(FunctionPrototype, {'constructor':Function}, default_attrs) 41 | 42 | #attach prototype to Function constructor 43 | Function.define_own_property('prototype', {'value': FunctionPrototype, 44 | 'enumerable': False, 45 | 'writable': False, 46 | 'configurable': False}) 47 | #Fix Function length (its 0 and should be 1) 48 | Function.own['length']['value'] = Js(1) 49 | 50 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsmath.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | import math 3 | import random 4 | 5 | Math = PyJsObject(prototype=ObjectPrototype) 6 | Math.Class = 'Math' 7 | 8 | CONSTANTS = {'E': 2.7182818284590452354, 9 | 'LN10': 2.302585092994046, 10 | 'LN2': 0.6931471805599453, 11 | 'LOG2E': 1.4426950408889634, 12 | 'LOG10E': 0.4342944819032518, 13 | 'PI': 3.1415926535897932, 14 | 'SQRT1_2': 0.7071067811865476, 15 | 'SQRT2': 1.4142135623730951} 16 | 17 | for constant, value in CONSTANTS.items(): 18 | Math.define_own_property(constant, {'value': Js(value), 19 | 'writable': False, 20 | 'enumerable': False, 21 | 'configurable': False}) 22 | 23 | class MathFunctions: 24 | def abs(x): 25 | a = x.to_number().value 26 | if a!=a: # it must be a nan 27 | return NaN 28 | return abs(a) 29 | 30 | def acos(x): 31 | a = x.to_number().value 32 | if a!=a: # it must be a nan 33 | return NaN 34 | try: 35 | return math.acos(a) 36 | except: 37 | return NaN 38 | 39 | def asin(x): 40 | a = x.to_number().value 41 | if a!=a: # it must be a nan 42 | return NaN 43 | try: 44 | return math.asin(a) 45 | except: 46 | return NaN 47 | 48 | def atan(x): 49 | a = x.to_number().value 50 | if a!=a: # it must be a nan 51 | return NaN 52 | return math.atan(a) 53 | 54 | def atan2(y, x): 55 | a = x.to_number().value 56 | b = y.to_number().value 57 | if a!=a or b!=b: # it must be a nan 58 | return NaN 59 | return math.atan2(b, a) 60 | 61 | def ceil(x): 62 | a = x.to_number().value 63 | if a!=a: # it must be a nan 64 | return NaN 65 | return math.ceil(a) 66 | 67 | def floor(x): 68 | a = x.to_number().value 69 | if a!=a: # it must be a nan 70 | return NaN 71 | return math.floor(a) 72 | 73 | def round(x): 74 | a = x.to_number().value 75 | if a!=a: # it must be a nan 76 | return NaN 77 | return round(a) 78 | 79 | def sin(x): 80 | a = x.to_number().value 81 | if a!=a: # it must be a nan 82 | return NaN 83 | return math.sin(a) 84 | 85 | def cos(x): 86 | a = x.to_number().value 87 | if a!=a: # it must be a nan 88 | return NaN 89 | return math.cos(a) 90 | 91 | def tan(x): 92 | a = x.to_number().value 93 | if a!=a: # it must be a nan 94 | return NaN 95 | return math.tan(a) 96 | 97 | def log(x): 98 | a = x.to_number().value 99 | if a!=a: # it must be a nan 100 | return NaN 101 | try: 102 | return math.log(a) 103 | except: 104 | return NaN 105 | 106 | def exp(x): 107 | a = x.to_number().value 108 | if a!=a: # it must be a nan 109 | return NaN 110 | return math.exp(a) 111 | 112 | def pow(x, y): 113 | a = x.to_number().value 114 | b = y.to_number().value 115 | if a!=a or b!=b: # it must be a nan 116 | return NaN 117 | try: 118 | return a**b 119 | except: 120 | return NaN 121 | 122 | def sqrt(x): 123 | a = x.to_number().value 124 | if a!=a: # it must be a nan 125 | return NaN 126 | try: 127 | return a**0.5 128 | except: 129 | return NaN 130 | 131 | def min(): 132 | if not len(arguments): 133 | return -Infinity 134 | lis = tuple(e.to_number().value for e in arguments.to_list()) 135 | if any(e!=e for e in lis): # we dont want NaNs 136 | return NaN 137 | return min(*lis) 138 | 139 | def max(): 140 | if not len(arguments): 141 | return -Infinity 142 | lis = tuple(e.to_number().value for e in arguments.to_list()) 143 | if any(e!=e for e in lis): # we dont want NaNs 144 | return NaN 145 | return max(*lis) 146 | 147 | def random(): 148 | return random.random() 149 | 150 | 151 | fill_prototype(Math, MathFunctions, default_attrs) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsnumber.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | 3 | 4 | CONSTS = {'prototype': NumberPrototype, 5 | 'MAX_VALUE':1.7976931348623157e308, 6 | 'MIN_VALUE': 5.0e-324, 7 | 'NaN': NaN, 8 | 'NEGATIVE_INFINITY': float('-inf'), 9 | 'POSITIVE_INFINITY': float('inf')} 10 | 11 | fill_in_props(Number, CONSTS, {'enumerable': False, 12 | 'writable': False, 13 | 'configurable': False}) 14 | 15 | NumberPrototype.define_own_property('constructor', {'value': Number, 16 | 'enumerable': False, 17 | 'writable': True, 18 | 'configurable': True}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsregexp.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | 3 | RegExpPrototype.define_own_property('constructor', {'value': RegExp, 4 | 'enumerable': False, 5 | 'writable': True, 6 | 'configurable': True}) 7 | 8 | RegExp.define_own_property('prototype', {'value': RegExpPrototype, 9 | 'enumerable': False, 10 | 'writable': False, 11 | 'configurable': False}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/jsstring.py: -------------------------------------------------------------------------------- 1 | from ..base import * 2 | # python 3 support 3 | import six 4 | if six.PY3: 5 | unichr = chr 6 | 7 | @Js 8 | def fromCharCode(): 9 | args = arguments.to_list() 10 | res = u'' 11 | for e in args: 12 | res +=unichr(e.to_uint16()) 13 | return this.Js(res) 14 | 15 | fromCharCode.own['length']['value'] = Js(1) 16 | 17 | String.define_own_property('fromCharCode', {'value': fromCharCode, 18 | 'enumerable': False, 19 | 'writable': True, 20 | 'configurable': True}) 21 | 22 | String.define_own_property('prototype', {'value': StringPrototype, 23 | 'enumerable': False, 24 | 'writable': False, 25 | 'configurable': False}) 26 | 27 | StringPrototype.define_own_property('constructor', {'value': String, 28 | 'enumerable': False, 29 | 'writable': True, 30 | 'configurable': True}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/constructors/time_helpers.py: -------------------------------------------------------------------------------- 1 | # NOTE: t must be INT!!! 2 | import time 3 | import datetime 4 | import warnings 5 | try: 6 | from tzlocal import get_localzone 7 | LOCAL_ZONE = get_localzone() 8 | except: # except all problems... 9 | class LOCAL_ZONE: 10 | @staticmethod 11 | def dst(*args): 12 | return 1 13 | 14 | from js2py.base import MakeError 15 | CUM = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) 16 | msPerDay = 86400000 17 | msPerYear = int(86400000*365.242) 18 | msPerSecond = 1000 19 | msPerMinute = 60000 20 | msPerHour = 3600000 21 | HoursPerDay = 24 22 | MinutesPerHour = 60 23 | SecondsPerMinute = 60 24 | NaN = float('nan') 25 | LocalTZA = - time.timezone * msPerSecond 26 | 27 | 28 | 29 | 30 | 31 | def DaylightSavingTA(t): 32 | if t is NaN: 33 | return t 34 | try: 35 | return int(LOCAL_ZONE.dst(datetime.datetime.utcfromtimestamp(t//1000)).seconds)*1000 36 | except: 37 | warnings.warn('Invalid datetime date, assumed DST time, may be inaccurate...', Warning) 38 | return 1 39 | #raise MakeError('TypeError', 'date not supported by python.datetime. I will solve it in future versions') 40 | 41 | def GetTimeZoneName(t): 42 | return time.tzname[DaylightSavingTA(t)>0] 43 | 44 | def LocalToUTC(t): 45 | return t - LocalTZA - DaylightSavingTA(t - LocalTZA) 46 | 47 | def UTCToLocal(t): 48 | return t + LocalTZA + DaylightSavingTA(t) 49 | 50 | 51 | def Day(t): 52 | return t//86400000 53 | 54 | 55 | def TimeWithinDay(t): 56 | return t%86400000 57 | 58 | def DaysInYear(y): 59 | if y%4: 60 | return 365 61 | elif y%100: 62 | return 366 63 | elif y%400: 64 | return 365 65 | else: 66 | return 366 67 | 68 | 69 | def DayFromYear(y): 70 | return 365 * (y-1970) + (y-1969)//4 -(y-1901)//100 + (y-1601)//400 71 | 72 | def TimeFromYear(y): 73 | return 86400000 * DayFromYear(y) 74 | 75 | def YearFromTime(t): 76 | guess = 1970 - t//31556908800 # msPerYear 77 | gt = TimeFromYear(guess) 78 | if gt<=t: 79 | while gt<=t: 80 | guess += 1 81 | gt = TimeFromYear(guess) 82 | return guess-1 83 | else: 84 | while gt>t: 85 | guess -= 1 86 | gt = TimeFromYear(guess) 87 | return guess 88 | 89 | 90 | def DayWithinYear(t): 91 | return Day(t) - DayFromYear(YearFromTime(t)) 92 | 93 | def InLeapYear(t): 94 | y = YearFromTime(t) 95 | if y%4: 96 | return 0 97 | elif y%100: 98 | return 1 99 | elif y%400: 100 | return 0 101 | else: 102 | return 1 103 | 104 | def MonthFromTime(t): 105 | day = DayWithinYear(t) 106 | leap = InLeapYear(t) 107 | if day<31: 108 | return 0 109 | day -= leap 110 | if day<59: 111 | return 1 112 | elif day<90: 113 | return 2 114 | elif day<120: 115 | return 3 116 | elif day<151: 117 | return 4 118 | elif day<181: 119 | return 5 120 | elif day<212: 121 | return 6 122 | elif day<243: 123 | return 7 124 | elif day<273: 125 | return 8 126 | elif day<304: 127 | return 9 128 | elif day<334: 129 | return 10 130 | else: 131 | return 11 132 | 133 | def DateFromTime(t): 134 | mon = MonthFromTime(t) 135 | day = DayWithinYear(t) 136 | return day-CUM[mon] - (1 if InLeapYear(t) and mon>=2 else 0) + 1 137 | 138 | def WeekDay(t): 139 | # 0 == sunday 140 | return (Day(t) + 4) % 7 141 | 142 | def msFromTime(t): 143 | return t % 1000 144 | 145 | def SecFromTime(t): 146 | return (t//1000) % 60 147 | 148 | def MinFromTime(t): 149 | return (t//60000) % 60 150 | 151 | def HourFromTime(t): 152 | return (t//3600000) % 24 153 | 154 | def MakeTime (hour, Min, sec, ms): 155 | # takes PyJs objects and returns t 156 | if not (hour.is_finite() and Min.is_finite() and sec.is_finite() and ms.is_finite()): 157 | return NaN 158 | h, m, s, milli = hour.to_int(), Min.to_int(), sec.to_int(), ms.to_int() 159 | return h*3600000 + m*60000 + s*1000 + milli 160 | 161 | 162 | def MakeDay(year, month, date): 163 | # takes PyJs objects and returns t 164 | if not (year.is_finite() and month.is_finite() and date.is_finite()): 165 | return NaN 166 | y, m, dt = year.to_int(), month.to_int(), date.to_int() 167 | y += m//12 168 | mn = m % 12 169 | d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y)==366 and mn>=2 else 0) 170 | return d # ms per day 171 | 172 | def MakeDate(day, time): 173 | return 86400000*day + time 174 | 175 | 176 | def TimeClip(t): 177 | if t!=t or abs(t)==float('inf'): 178 | return NaN 179 | if abs(t) > 8.64 *10**15: 180 | return NaN 181 | return int(t) 182 | 183 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/host/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/I-A-C/script.module.openscrapers/3bd73e93339cc2f2e5df0570aaa145dc8d5550b7/lib/openscrapers/modules/js2py/host/__init__.py -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/host/console.py: -------------------------------------------------------------------------------- 1 | from js2py.base import * 2 | 3 | @Js 4 | def console(): 5 | pass 6 | 7 | @Js 8 | def log(): 9 | print(arguments[0]) 10 | 11 | console.put('log', log) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/host/dom/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/I-A-C/script.module.openscrapers/3bd73e93339cc2f2e5df0570aaa145dc8d5550b7/lib/openscrapers/modules/js2py/host/dom/__init__.py -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/host/dom/constants.py: -------------------------------------------------------------------------------- 1 | from js2py.base import * 2 | 3 | def _get_conts(idl): 4 | def is_valid(c): 5 | try: 6 | exec(c) 7 | return 1 8 | except: 9 | pass 10 | return '\n'.join(filter(is_valid, (' '.join(e.strip(' ;').split()[-3:]) for e in idl.splitlines()))) 11 | 12 | 13 | default_attrs = {'writable':True, 'enumerable':True, 'configurable':True} 14 | 15 | 16 | def compose_prototype(Class, attrs=default_attrs): 17 | prototype = Class() 18 | for i in dir(Class): 19 | e = getattr(Class, i) 20 | if hasattr(e, '__func__'): 21 | temp = PyJsFunction(e.__func__, FunctionPrototype) 22 | attrs = {k:v for k,v in attrs.iteritems()} 23 | attrs['value'] = temp 24 | prototype.define_own_property(i, attrs) 25 | return prototype 26 | 27 | 28 | # Error codes 29 | 30 | INDEX_SIZE_ERR = 1 31 | DOMSTRING_SIZE_ERR = 2 32 | HIERARCHY_REQUEST_ERR = 3 33 | WRONG_DOCUMENT_ERR = 4 34 | INVALID_CHARACTER_ERR = 5 35 | NO_DATA_ALLOWED_ERR = 6 36 | NO_MODIFICATION_ALLOWED_ERR = 7 37 | NOT_FOUND_ERR = 8 38 | NOT_SUPPORTED_ERR = 9 39 | INUSE_ATTRIBUTE_ERR = 10 40 | INVALID_STATE_ERR = 11 41 | SYNTAX_ERR = 12 42 | INVALID_MODIFICATION_ERR = 13 43 | NAMESPACE_ERR = 14 44 | INVALID_ACCESS_ERR = 15 45 | VALIDATION_ERR = 16 46 | TYPE_MISMATCH_ERR = 17 47 | 48 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/host/dom/interface.py: -------------------------------------------------------------------------------- 1 | from StringIO import StringIO 2 | from constants import * 3 | from bs4 import BeautifulSoup 4 | from js2py.base import * 5 | try: 6 | import lxml 7 | def parse(source): 8 | return BeautifulSoup(source, 'lxml') 9 | except: 10 | def parse(source): 11 | return BeautifulSoup(source) 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | x = ''' 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
Shady GroveAeolian
Over the River, CharlieDorian
''' 31 | 32 | 33 | 34 | class DOM(PyJs): 35 | prototype = ObjectPrototype 36 | def __init__(self): 37 | self.own = {} 38 | 39 | def readonly(self, name, val): 40 | self.define_own_property(name, {'writable':False, 'enumerable':False, 'configurable':False, 'value': Js(val)}) 41 | 42 | 43 | 44 | # DOMStringList 45 | 46 | class DOMStringListPrototype(DOM): 47 | Class = 'DOMStringListPrototype' 48 | 49 | def contains(element): 50 | return element.to_string().value in this._string_list 51 | 52 | def item(index): 53 | return this._string_list[index.to_int()] if 0<=index.to_int()36: 21 | return NaN 22 | if r!=16: 23 | strip_prefix = False 24 | else: 25 | r = 10 26 | if strip_prefix: 27 | if len(string)>=2 and string[:2] in ['0x', '0X']: 28 | string = string[2:] 29 | r = 16 30 | n = 0 31 | num = 0 32 | while n4: # cant be a number anymore 62 | break 63 | length += 1 64 | if num is None: 65 | return NaN 66 | return sign*float(string[:max_len]) 67 | 68 | @Js 69 | def isNaN(number): 70 | if number.to_number().is_nan(): 71 | return true 72 | return false 73 | 74 | @Js 75 | def isFinite(number): 76 | num = number.to_number() 77 | if num.is_nan() or num.is_infinity(): 78 | return false 79 | return true 80 | 81 | 82 | #todo URI handling! 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/legecy_translators/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Piotrek' 2 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/legecy_translators/exps.py: -------------------------------------------------------------------------------- 1 | """ 2 | exp_translate routine: 3 | It takes a single line of JS code and returns a SINGLE line of Python code. 4 | Note var is not present here because it was removed in previous stages. Also remove this useless void keyword 5 | If case of parsing errors it must return a pos of error. 6 | 1. Convert all assignment operations to put operations, this may be hard :( DONE, wasn't that bad 7 | 2. Convert all gets and calls to get and callprop. 8 | 3. Convert unary operators like typeof, new, !, delete, ++, -- 9 | Delete can be handled by replacing last get method with delete. 10 | 4. Convert remaining operators that are not handled by python: 11 | &&, || <= these should be easy simply replace && by and and || by or 12 | === and !== 13 | comma operator , in, instanceof and finally :? 14 | 15 | 16 | NOTES: 17 | Strings and other literals are not present so each = means assignment 18 | """ 19 | from utils import * 20 | from jsparser import * 21 | 22 | def exps_translator(js): 23 | #Check () {} and [] nums 24 | ass = assignment_translator(js) 25 | 26 | 27 | # Step 1 28 | def assignment_translator(js): 29 | sep = js.split(',') 30 | res = sep[:] 31 | for i, e in enumerate(sep): 32 | if '=' not in e: # no need to convert 33 | continue 34 | res[i] = bass_translator(e) 35 | return ','.join(res) 36 | 37 | 38 | def bass_translator(s): 39 | # I hope that I will not have to fix any bugs here because it will be terrible 40 | if '(' in s or '[' in s: 41 | converted = '' 42 | for e in bracket_split(s, ['()','[]'], strip=False): 43 | if e[0]=='(': 44 | converted += '(' + bass_translator(e[1:-1])+')' 45 | elif e[0]=='[': 46 | converted += '[' + bass_translator(e[1:-1])+']' 47 | else: 48 | converted += e 49 | s = converted 50 | if '=' not in s: 51 | return s 52 | ass = reversed(s.split('=')) 53 | last = ass.next() 54 | res = last 55 | for e in ass: 56 | op = '' 57 | if e[-1] in OP_METHODS: #increment assign like += 58 | op = ', "'+e[-1]+'"' 59 | e = e[:-1] 60 | cand = e.strip('() ') # (a) = 40 is valid so we need to transform '(a) ' to 'a' 61 | if not is_property_accessor(cand): # it is not a property assignment 62 | if not is_lval(cand) or is_internal(cand): 63 | raise SyntaxError('Invalid left-hand side in assignment') 64 | res = 'var.put(%s, %s%s)'%(cand.__repr__(), res, op) 65 | elif cand[-1]==']': # property assignment via [] 66 | c = list(bracket_split(cand, ['[]'], strip=False)) 67 | meth, prop = ''.join(c[:-1]).strip(), c[-1][1:-1].strip() #this does not have to be a string so dont remove 68 | #() because it can be a call 69 | res = '%s.put(%s, %s%s)'%(meth, prop, res, op) 70 | else: # Prop set via '.' 71 | c = cand.rfind('.') 72 | meth, prop = cand[:c].strip(), cand[c+1:].strip('() ') 73 | if not is_lval(prop): 74 | raise SyntaxError('Invalid left-hand side in assignment') 75 | res = '%s.put(%s, %s%s)'%(meth, prop.__repr__(), res, op) 76 | return res 77 | 78 | if __name__=='__main__': 79 | print bass_translator('3.ddsd = 40') -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/legecy_translators/functions.py: -------------------------------------------------------------------------------- 1 | """This module removes JS functions from source code""" 2 | from jsparser import * 3 | from utils import * 4 | 5 | 6 | INLINE_NAME = 'PyJsLvalInline%d_' 7 | INLINE_COUNT = 0 8 | PRE_EXP_STARTS = {'return', 'new', 'void', 'throw', 'typeof', 'in', 'instanceof'} 9 | PRE_ALLOWED = IDENTIFIER_PART.union({';', '{', '}', ']', ')', ':'}) 10 | INCREMENTS = {'++', '--'} 11 | 12 | def reset_inline_count(): 13 | global INLINE_COUNT 14 | INLINE_COUNT = 0 15 | 16 | def remove_functions(source, all_inline=False): 17 | """removes functions and returns new source, and 2 dicts. 18 | first dict with removed hoisted(global) functions and second with replaced inline functions""" 19 | global INLINE_COUNT 20 | inline = {} 21 | hoisted = {} 22 | n = 0 23 | limit = len(source) - 9 # 8 is length of 'function' 24 | res = '' 25 | last = 0 26 | while n < limit: 27 | if n and source[n-1] in IDENTIFIER_PART: 28 | n+=1 29 | continue 30 | if source[n:n+8] == 'function' and source[n+8] not in IDENTIFIER_PART: 31 | if source[:n].rstrip().endswith('.'): # allow function as a property name :) 32 | n+=1 33 | continue 34 | if source[n+8:].lstrip().startswith(':'): # allow functions inside objects... 35 | n+=1 36 | continue 37 | entered = n 38 | res += source[last:n] 39 | name = '' 40 | n = pass_white(source, n+8) 41 | if source[n] in IDENTIFIER_START: # hoisted function 42 | name, n= parse_identifier(source, n) 43 | args, n = pass_bracket(source, n, '()') 44 | if not args: 45 | raise SyntaxError('Function misses bracket with argnames ()') 46 | args = args.strip('() \n') 47 | args = tuple(parse_identifier(e, 0)[0] for e in argsplit(args)) if args else () 48 | if len(args) - len(set(args)): 49 | # I know its legal in JS but python does not allow duplicate argnames 50 | # I will not work around it 51 | raise SyntaxError('Function has duplicate argument names. Its not legal in this implementation. Sorry.') 52 | block, n = pass_bracket(source, n, '{}') 53 | if not block: 54 | raise SyntaxError('Function does not have any code block to execute') 55 | mixed = False # named function expression flag 56 | if name and not all_inline: 57 | # Here I will distinguish between named function expression (mixed) and a function statement 58 | before = source[:entered].rstrip() 59 | if any(endswith_keyword(before, e) for e in PRE_EXP_STARTS): 60 | #print 'Ended ith keyword' 61 | mixed = True 62 | elif before and before[-1] not in PRE_ALLOWED and not before[-2:] in INCREMENTS: 63 | #print 'Ended with'+repr(before[-1]), before[-1]=='}' 64 | mixed = True 65 | else: 66 | #print 'FUNCTION STATEMENT' 67 | #its a function statement. 68 | # todo remove fucking label if present! 69 | hoisted[name] = block, args 70 | if not name or mixed or all_inline: # its a function expression (can be both named and not named) 71 | #print 'FUNCTION EXPRESSION' 72 | INLINE_COUNT += 1 73 | iname = INLINE_NAME%INLINE_COUNT # inline name 74 | res += ' '+ iname 75 | inline['%s@%s' %(iname, name)] = block, args #here added real name at the end because it has to be added to the func scope 76 | last = n 77 | else: 78 | n+=1 79 | res += source[last:] 80 | return res, hoisted, inline 81 | 82 | 83 | if __name__=='__main__': 84 | print remove_functions('5+5 function n (functiona ,functionaj) {dsd s, dsdd}') -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/legecy_translators/tokenize.py: -------------------------------------------------------------------------------- 1 | from jsparser import * 2 | from utils import * 3 | # maybe I will try rewriting my parser in the future... Tokenizer makes things much easier and faster, unfortunately I 4 | # did not know anything about parsers when I was starting this project so I invented my own. 5 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/legecy_translators/utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unicodedata 3 | from collections import defaultdict 4 | 5 | def is_lval(t): 6 | """Does not chceck whether t is not resticted or internal""" 7 | if not t: 8 | return False 9 | i = iter(t) 10 | if i.next() not in IDENTIFIER_START: 11 | return False 12 | return all(e in IDENTIFIER_PART for e in i) 13 | 14 | def is_valid_lval(t): 15 | """Checks whether t is valid JS identifier name (no keyword like var, function, if etc) 16 | Also returns false on internal""" 17 | if not is_internal(t) and is_lval(t) and t not in RESERVED_NAMES: 18 | return True 19 | return False 20 | 21 | 22 | def is_plval(t): 23 | return t.startswith('PyJsLval') 24 | 25 | def is_marker(t): 26 | return t.startswith('PyJsMarker') or t.startswith('PyJsConstant') 27 | 28 | def is_internal(t): 29 | return is_plval(t) or is_marker(t) or t=='var' # var is a scope var 30 | 31 | def is_property_accessor(t): 32 | return '[' in t or '.' in t 33 | 34 | def is_reserved(t): 35 | return t in RESERVED_NAMES 36 | 37 | 38 | 39 | 40 | #http://stackoverflow.com/questions/14245893/efficiently-list-all-characters-in-a-given-unicode-category 41 | BOM = u'\uFEFF' 42 | ZWJ = u'\u200D' 43 | ZWNJ = u'\u200C' 44 | TAB = u'\u0009' 45 | VT = u'\u000B' 46 | FF = u'\u000C' 47 | SP = u'\u0020' 48 | NBSP = u'\u00A0' 49 | LF = u'\u000A' 50 | CR = u'\u000D' 51 | LS = u'\u2028' 52 | PS = u'\u2029' 53 | 54 | U_CATEGORIES = defaultdict(list) # Thank you Martijn Pieters! 55 | for c in map(unichr, range(sys.maxunicode + 1)): 56 | U_CATEGORIES[unicodedata.category(c)].append(c) 57 | 58 | UNICODE_LETTER = set(U_CATEGORIES['Lu']+U_CATEGORIES['Ll']+ 59 | U_CATEGORIES['Lt']+U_CATEGORIES['Lm']+ 60 | U_CATEGORIES['Lo']+U_CATEGORIES['Nl']) 61 | UNICODE_COMBINING_MARK = set(U_CATEGORIES['Mn']+U_CATEGORIES['Mc']) 62 | UNICODE_DIGIT = set(U_CATEGORIES['Nd']) 63 | UNICODE_CONNECTOR_PUNCTUATION = set(U_CATEGORIES['Pc']) 64 | IDENTIFIER_START = UNICODE_LETTER.union({'$','_'}) # and some fucking unicode escape sequence 65 | IDENTIFIER_PART = IDENTIFIER_START.union(UNICODE_COMBINING_MARK).union(UNICODE_DIGIT).union(UNICODE_CONNECTOR_PUNCTUATION).union({ZWJ, ZWNJ}) 66 | USP = U_CATEGORIES['Zs'] 67 | KEYWORD = {'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 68 | 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 69 | 'switch', 'while', 'debugger', 'function', 'this', 'with', 'default', 70 | 'if', 'throw', 'delete', 'in', 'try'} 71 | 72 | FUTURE_RESERVED_WORD = {'class', 'enum', 'extends', 'super', 'const', 'export', 'import'} 73 | RESERVED_NAMES = KEYWORD.union(FUTURE_RESERVED_WORD).union({'null', 'false', 'true'}) 74 | 75 | WHITE = {TAB, VT, FF, SP, NBSP, BOM}.union(USP) 76 | LINE_TERMINATOR = {LF, CR, LS, PS} 77 | LLINE_TERMINATOR = list(LINE_TERMINATOR) 78 | x = ''.join(WHITE)+''.join(LINE_TERMINATOR) 79 | SPACE = WHITE.union(LINE_TERMINATOR) 80 | LINE_TERMINATOR_SEQUENCE = LINE_TERMINATOR.union({CR+LF}) -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'Piotr Dabkowski' 2 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jsboolean.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class BooleanPrototype: 4 | def toString(): 5 | if this.Class!='Boolean': 6 | raise this.Js(TypeError)('this must be a boolean') 7 | return 'true' if this.value else 'false' 8 | 9 | def valueOf(): 10 | if this.Class!='Boolean': 11 | raise this.Js(TypeError)('this must be a boolean') 12 | return this.value 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jserror.py: -------------------------------------------------------------------------------- 1 | 2 | class ErrorPrototype: 3 | def toString(): 4 | if this.TYPE!='Object': 5 | raise this.MakeError('TypeError', 'Error.prototype.toString called on non-object') 6 | name = this.get('name') 7 | name = 'Error' if name.is_undefined() else name.to_string().value 8 | msg = this.get('message') 9 | msg = '' if msg.is_undefined() else msg.to_string().value 10 | return name + (name and msg and ': ') + msg -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jsfunction.py: -------------------------------------------------------------------------------- 1 | # python 3 support 2 | import six 3 | if six.PY3: 4 | basestring = str 5 | long = int 6 | xrange = range 7 | unicode = str 8 | 9 | 10 | # todo fix apply and bind 11 | 12 | class FunctionPrototype: 13 | def toString(): 14 | if not this.is_callable(): 15 | raise TypeError('toString is not generic!') 16 | args = ', '.join(this.code.__code__.co_varnames[:this.argcount]) 17 | return 'function %s(%s) '%(this.func_name, args)+this.source 18 | 19 | def call(): 20 | arguments_ = arguments 21 | if not len(arguments): 22 | obj = this.Js(None) 23 | else: 24 | obj = arguments[0] 25 | if len(arguments)<=1: 26 | args = () 27 | else: 28 | args = tuple([arguments_[e] for e in xrange(1, len(arguments_))]) 29 | return this.call(obj, args) 30 | 31 | def apply(): 32 | if not len(arguments): 33 | obj = this.Js(None) 34 | else: 35 | obj = arguments[0] 36 | if len(arguments)<=1: 37 | args = () 38 | else: 39 | appl = arguments[1] 40 | args = tuple([appl[e] for e in xrange(len(appl))]) 41 | return this.call(obj, args) 42 | 43 | def bind(thisArg): 44 | target = this 45 | if not target.is_callable(): 46 | raise this.MakeError('Object must be callable in order to be used with bind method') 47 | if len(arguments) <= 1: 48 | args = () 49 | else: 50 | args = tuple([arguments[e] for e in xrange(1, len(arguments))]) 51 | return this.PyJsBoundFunction(target, thisArg, args) 52 | 53 | 54 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jsnumber.py: -------------------------------------------------------------------------------- 1 | import six 2 | if six.PY3: 3 | basestring = str 4 | long = int 5 | xrange = range 6 | unicode = str 7 | 8 | 9 | RADIX_SYMBOLS = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10 | 10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f', 16: 'g', 17: 'h', 18: 'i', 19: 'j', 20: 'k', 11 | 21: 'l', 22: 'm', 23: 'n', 24: 'o', 25: 'p', 26: 'q', 27: 'r', 28: 's', 29: 't', 30: 'u', 31: 'v', 12 | 32: 'w', 33: 'x', 34: 'y', 35: 'z'} 13 | 14 | 15 | def to_str_rep(num): 16 | if num.is_nan(): 17 | return num.Js('NaN') 18 | elif num.is_infinity(): 19 | sign = '-' if num.value<0 else '' 20 | return num.Js(sign+'Infinity') 21 | elif isinstance(num.value, (long, int)) or num.value.is_integer(): # dont print .0 22 | return num.Js(unicode(int(num.value))) 23 | return num.Js(unicode(num.value)) # accurate enough 24 | 25 | 26 | class NumberPrototype: 27 | def toString(radix): 28 | if this.Class!='Number': 29 | raise this.MakeError('TypeError', 'Number.prototype.valueOf is not generic') 30 | if radix.is_undefined(): 31 | return to_str_rep(this) 32 | r = radix.to_int() 33 | if r==10: 34 | return to_str_rep(this) 35 | if r not in xrange(2, 37): 36 | raise this.MakeError('RangeError', 'Number.prototype.toString() radix argument must be between 2 and 36') 37 | num = this.to_int() 38 | if num < 0: 39 | num = -num 40 | sign = '-' 41 | else: 42 | sign = '' 43 | res = '' 44 | while num: 45 | s = RADIX_SYMBOLS[num % r] 46 | num = num // r 47 | res = s + res 48 | return sign + (res if res else '0') 49 | 50 | def valueOf(): 51 | if this.Class!='Number': 52 | raise this.MakeError('TypeError', 'Number.prototype.valueOf is not generic') 53 | return this.value 54 | 55 | def toLocaleString(): 56 | return this.to_string() 57 | 58 | def toFixed (fractionDigits): 59 | if this.Class!='Number': 60 | raise this.MakeError('TypeError', 'Number.prototype.toFixed called on incompatible receiver') 61 | digs = fractionDigits.to_int() 62 | if digs<0 or digs>20: 63 | raise this.MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20') 64 | elif this.is_infinity(): 65 | return 'Infinity' if this.value>0 else '-Infinity' 66 | elif this.is_nan(): 67 | return 'NaN' 68 | return format(this.value, '-.%df'%digs) 69 | 70 | 71 | def toExponential (fractionDigits): 72 | if this.Class!='Number': 73 | raise this.MakeError('TypeError', 'Number.prototype.toExponential called on incompatible receiver') 74 | digs = fractionDigits.to_int() 75 | if digs<0 or digs>20: 76 | raise this.MakeError('RangeError', 'toFixed() digits argument must be between 0 and 20') 77 | elif this.is_infinity(): 78 | return 'Infinity' if this.value>0 else '-Infinity' 79 | elif this.is_nan(): 80 | return 'NaN' 81 | return format(this.value, '-.%de'%digs) 82 | 83 | def toPrecision (precision): 84 | if this.Class!='Number': 85 | raise this.MakeError('TypeError', 'Number.prototype.toPrecision called on incompatible receiver') 86 | if precision.is_undefined(): 87 | return this.to_String() 88 | prec = precision.to_int() 89 | if this.is_nan(): 90 | return 'NaN' 91 | elif this.is_infinity(): 92 | return 'Infinity' if this.value>0 else '-Infinity' 93 | digs = prec - len(str(int(this.value))) 94 | if digs>=0: 95 | return format(this.value, '-.%df'%digs) 96 | else: 97 | return format(this.value, '-.%df'%(prec-1)) 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jsobject.py: -------------------------------------------------------------------------------- 1 | 2 | class ObjectPrototype: 3 | def toString(): 4 | return '[object %s]'%this.Class 5 | 6 | def valueOf(): 7 | return this.to_object() 8 | 9 | 10 | def toLocaleString(): 11 | return this.callprop('toString') 12 | 13 | def hasOwnProperty(prop): 14 | return this.get_own_property(prop.to_string().value) is not None 15 | 16 | def isPrototypeOf(obj): 17 | #a bit stupid specification but well 18 | # for example Object.prototype.isPrototypeOf.call((5).__proto__, 5) gives false 19 | if not obj.is_object(): 20 | return False 21 | while 1: 22 | obj = obj.prototype 23 | if obj is None or obj.is_null(): 24 | return False 25 | if obj is this: 26 | return True 27 | 28 | def propertyIsEnumerable(prop): 29 | cand = this.own.get(prop.to_string().value) 30 | return cand is not None and cand.get('enumerable') 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/prototypes/jsregexp.py: -------------------------------------------------------------------------------- 1 | 2 | class RegExpPrototype: 3 | def toString(): 4 | flags = u'' 5 | if this.glob: 6 | flags += u'g' 7 | if this.ignore_case: 8 | flags += u'i' 9 | if this.multiline: 10 | flags += u'm' 11 | v = this.value if this.value else '(?:)' 12 | return u'/%s/'%v + flags 13 | 14 | def test(string): 15 | return Exec(this, string) is not this.null 16 | 17 | def exec2(string): # will be changed to exec in base.py. cant name it exec here 18 | return Exec(this, string) 19 | 20 | 21 | 22 | 23 | def Exec(this, string): 24 | if this.Class!='RegExp': 25 | raise this.MakeError('TypeError', 'RegExp.prototype.exec is not generic!') 26 | string = string.to_string() 27 | length = len(string) 28 | i = this.get('lastIndex').to_int() if this.glob else 0 29 | matched = False 30 | while not matched: 31 | if i < 0 or i > length: 32 | this.put('lastIndex', this.Js(0)) 33 | return this.null 34 | matched = this.match(string.value, i) 35 | i += 1 36 | start, end = matched.span()#[0]+i-1, matched.span()[1]+i-1 37 | if this.glob: 38 | this.put('lastIndex', this.Js(end)) 39 | arr = this.Js([this.Js(e) for e in [matched.group()]+list(matched.groups())]) 40 | arr.put('index', this.Js(start)) 41 | arr.put('input', string) 42 | return arr 43 | 44 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/pyjs.py: -------------------------------------------------------------------------------- 1 | from .base import * 2 | from .constructors.jsmath import Math 3 | from .constructors.jsdate import Date 4 | from .constructors.jsobject import Object 5 | from .constructors.jsfunction import Function 6 | from .constructors.jsstring import String 7 | from .constructors.jsnumber import Number 8 | from .constructors.jsboolean import Boolean 9 | from .constructors.jsregexp import RegExp 10 | from .constructors.jsarray import Array 11 | from .prototypes.jsjson import JSON 12 | from .host.console import console 13 | from .host.jseval import Eval 14 | from .host.jsfunctions import parseFloat, parseInt, isFinite, isNaN 15 | 16 | # Now we have all the necessary items to create global environment for script 17 | __all__ = ['Js', 'PyJsComma', 'PyJsStrictEq', 'PyJsStrictNeq', 18 | 'PyJsException', 'PyJsBshift', 'Scope', 'PyExceptionToJs', 19 | 'JsToPyException', 'JS_BUILTINS', 'appengine', 'set_global_object', 20 | 'JsRegExp', 'PyJsException', 'PyExceptionToJs', 'JsToPyException', 'PyJsSwitchException'] 21 | 22 | 23 | # these were defined in base.py 24 | builtins = ('true','false','null','undefined','Infinity', 25 | 'NaN', 'console', 'String', 'Number', 'Boolean', 'RegExp', 26 | 'Math', 'Date', 'Object', 'Function', 'Array', 27 | 'parseFloat', 'parseInt', 'isFinite', 'isNaN') 28 | #Array, Function, JSON, Error is done later :) 29 | # also some built in functions like eval... 30 | 31 | def set_global_object(obj): 32 | obj.IS_CHILD_SCOPE = False 33 | this = This({}) 34 | this.own = obj.own 35 | this.prototype = obj.prototype 36 | PyJs.GlobalObject = this 37 | # make this available 38 | obj.register('this') 39 | obj.put('this', this) 40 | 41 | 42 | 43 | scope = dict(zip(builtins, [globals()[e] for e in builtins])) 44 | # Now add errors: 45 | for name, error in ERRORS.items(): 46 | scope[name] = error 47 | #add eval 48 | scope['eval'] = Eval 49 | scope['JSON'] = JSON 50 | JS_BUILTINS = {} 51 | for k,v in scope.iteritems(): 52 | JS_BUILTINS[k]=v 53 | 54 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/todo: -------------------------------------------------------------------------------- 1 | # TODO 2 | Check Object Constructor 3 | Complete list prototype 4 | Fix function bind... 5 | Fix regexp compile ??? 6 | Check prototypes: 7 | String: replace, split 8 | fix recursion error in special case in to_dict and to_list 9 | 10 | Array constructor 11 | 12 | 13 | escape, URL... etc 14 | 15 | Check primitive.to_object() 16 | var obj = new Number(0); var x = new Array(obj); x 17 | 18 | Smarter import... 19 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/translators/__init__.py: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | # 3 | # Copyright 2014, 2015 Piotr Dabkowski 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 'Software'), 7 | # to deal in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | # the Software, and to permit persons to whom the Software is furnished to do so, subject 10 | # to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all copies or 13 | # substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 16 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 20 | 21 | __all__ = ['PyJsParser', 'Node', 'WrappingNode', 'node_to_dict', 'parse', 'translate_js', 'translate', 'syntax_tree_translate', 22 | 'DEFAULT_HEADER'] 23 | __author__ = 'Piotr Dabkowski' 24 | __version__ = '2.2.0' 25 | from .pyjsparser import PyJsParser, Node, WrappingNode, node_to_dict 26 | from .translator import translate_js, trasnlate, syntax_tree_translate, DEFAULT_HEADER 27 | 28 | 29 | def parse(javascript_code): 30 | """Returns syntax tree of javascript_code. 31 | 32 | Syntax tree has the same structure as syntax tree produced by esprima.js 33 | 34 | Same as PyJsParser().parse For your convenience :) """ 35 | p = PyJsParser() 36 | return p.parse(javascript_code) 37 | 38 | 39 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/I-A-C/script.module.openscrapers/3bd73e93339cc2f2e5df0570aaa145dc8d5550b7/lib/openscrapers/modules/js2py/utils/__init__.py -------------------------------------------------------------------------------- /lib/openscrapers/modules/js2py/utils/definitions.py: -------------------------------------------------------------------------------- 1 | from pyparsing import * 2 | IdentifierStart = oneOf(['$', '_']+list(alphas)) 3 | Identifier = Combine(IdentifierStart + Optional(Word(alphas+nums+'$_'))) 4 | 5 | _keywords = ['break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 6 | 'return', 'void', 'continue', 'for', 'switch', 'while', 'debugger', 'function', 'this', 7 | 'with', 'default', 'if', 'throw', 'delete', 'in', 'try'] 8 | 9 | Keyword = oneOf(_keywords) 10 | 11 | 12 | #Literals 13 | 14 | #Bool 15 | BooleanLiteral = oneOf(('true', 'false')) 16 | 17 | #Null 18 | 19 | NullLiteral = Literal('null') 20 | 21 | #Undefined 22 | 23 | UndefinedLiteral = Literal('undefined') 24 | 25 | #NaN 26 | 27 | NaNLiteral = Literal('NaN') 28 | 29 | #Number 30 | NonZeroDigit = oneOf(['1','2','3','4','5','6','7','8','9']) 31 | DecimalDigit = oneOf(['0', '1','2','3','4','5','6','7','8','9']) 32 | HexDigit = oneOf(list('0123456789abcdefABCDEF')) 33 | DecimalDigits = Word(nums) 34 | DecimalIntegerLiteral = Combine(NonZeroDigit+Optional(DecimalDigits)) | '0' 35 | SignedInteger = Combine('-'+DecimalDigits) | Combine('+'+DecimalDigits) | DecimalDigits 36 | ExponentPart = Combine(oneOf('e', 'E')+SignedInteger) 37 | _DecimalLiteral = (Combine(DecimalIntegerLiteral('int')+'.'+Optional(DecimalDigits('float'))+Optional(ExponentPart('exp'))) | 38 | Combine('.'+DecimalDigits('float')+Optional(ExponentPart('exp'))) | 39 | DecimalIntegerLiteral('int')+Optional(ExponentPart('exp'))) 40 | DecimalLiteral = Combine(_DecimalLiteral+NotAny(IdentifierStart)) 41 | HexIntegerLiteral = Combine(oneOf(('0x','0X'))+Word('0123456789abcdefABCDEF')('hex')) 42 | NumericLiteral = Group(DecimalLiteral)('decimal') ^ Group(HexIntegerLiteral)('hex') 43 | 44 | def js_num(num): 45 | res = NumericLiteral.parseString(num) 46 | if res.decimal: 47 | res = res.decimal 48 | cand = int(res.int if res.int else 0)+ float('0.'+res.float if res.float else 0) 49 | if res.exp: 50 | cand*= 10**int(res.exp) 51 | return cand 52 | elif res.hex: 53 | return int(res.hex.hex, 16) 54 | 55 | #String 56 | LineTerminator = White('\n', 1,1,1) | White('\r', 1,1,1) 57 | LineTerminatorSequence = Combine(White('\r', 1,1,1)+White('\n', 1,1,1)) | White('\n', 1,1,1) | White('\r', 1,1,1) 58 | LineContinuation = Combine('\\'+LineTerminatorSequence) 59 | 60 | UnicodeEscapeSequence = Combine('u'+HexDigit+HexDigit+HexDigit+HexDigit) 61 | HexEscapeSequence = Combine('x'+HexDigit+HexDigit) 62 | SingleEscapeCharacter = oneOf(["'", '"', '\\', 'b', 'f', 'n', 'r', 't', 'v']) 63 | EscapeCharacter = SingleEscapeCharacter | '0' | 'x' | 'u' # Changed DecimalDigit to 0 since it would match for example "\3" To verify.. 64 | NonEscapeCharacter = CharsNotIn([EscapeCharacter |LineTerminator]) 65 | CharacterEscapeSequence = SingleEscapeCharacter | NonEscapeCharacter 66 | EscapeSequence = CharacterEscapeSequence | Combine('0'+NotAny(DecimalDigit)) | HexEscapeSequence | UnicodeEscapeSequence 67 | 68 | SingleStringCharacter = CharsNotIn([LineTerminator | '\\' | "'"]) | Combine('\\'+EscapeSequence) | LineContinuation 69 | DoubleStringCharacter = CharsNotIn([LineTerminator | '\\' | '"']) | Combine('\\'+EscapeSequence) | LineContinuation 70 | StringLiteral = Combine('"'+ZeroOrMore(DoubleStringCharacter)+'"') ^ Combine("'"+ZeroOrMore(SingleStringCharacter)+"'") 71 | 72 | #Array 73 | 74 | 75 | #Dict 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/pyaes/__init__.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) 2014 Richard Moore 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | # This is a pure-Python implementation of the AES algorithm and AES common 24 | # modes of operation. 25 | 26 | # See: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard 27 | # See: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation 28 | 29 | 30 | # Supported key sizes: 31 | # 128-bit 32 | # 192-bit 33 | # 256-bit 34 | 35 | 36 | # Supported modes of operation: 37 | # ECB - Electronic Codebook 38 | # CBC - Cipher-Block Chaining 39 | # CFB - Cipher Feedback 40 | # OFB - Output Feedback 41 | # CTR - Counter 42 | 43 | # See the README.md for API details and general information. 44 | 45 | # Also useful, PyCrypto, a crypto library implemented in C with Python bindings: 46 | # https://www.dlitz.net/software/pycrypto/ 47 | 48 | 49 | VERSION = [1, 3, 0] 50 | 51 | from .aes import AES, AESModeOfOperationCTR, AESModeOfOperationCBC, AESModeOfOperationCFB, AESModeOfOperationECB, AESModeOfOperationOFB, AESModesOfOperation, Counter 52 | from .blockfeeder import decrypt_stream, Decrypter, encrypt_stream, Encrypter 53 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/pyaes/util.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # 3 | # Copyright (c) 2014 Richard Moore 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | # Why to_bufferable? 24 | # Python 3 is very different from Python 2.x when it comes to strings of text 25 | # and strings of bytes; in Python 3, strings of bytes do not exist, instead to 26 | # represent arbitrary binary data, we must use the "bytes" object. This method 27 | # ensures the object behaves as we need it to. 28 | 29 | def to_bufferable(binary): 30 | return binary 31 | 32 | def _get_byte(c): 33 | return ord(c) 34 | 35 | try: 36 | xrange 37 | except: 38 | 39 | def to_bufferable(binary): 40 | if isinstance(binary, bytes): 41 | return binary 42 | return bytes(ord(b) for b in binary) 43 | 44 | def _get_byte(c): 45 | return c 46 | 47 | def append_PKCS7_padding(data): 48 | pad = 16 - (len(data) % 16) 49 | return data + to_bufferable(chr(pad) * pad) 50 | 51 | def strip_PKCS7_padding(data): 52 | if len(data) % 16 != 0: 53 | raise ValueError("invalid length") 54 | 55 | pad = _get_byte(data[-1]) 56 | 57 | if not pad or pad > 16: 58 | return data 59 | 60 | return data[:-pad] 61 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/tvmaze.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | 23 | import urllib,json 24 | 25 | from openscrapers.modules import cache 26 | from openscrapers.modules import client 27 | 28 | 29 | class tvMaze: 30 | def __init__(self, show_id = None): 31 | self.api_url = 'http://api.tvmaze.com/%s%s' 32 | self.show_id = show_id 33 | 34 | 35 | def showID(self, show_id = None): 36 | if (show_id != None): 37 | self.show_id = show_id 38 | return show_id 39 | 40 | return self.show_id 41 | 42 | 43 | def request(self, endpoint, query = None): 44 | try: 45 | # Encode the queries, if there is any... 46 | if (query != None): 47 | query = '?' + urllib.urlencode(query) 48 | else: 49 | query = '' 50 | 51 | # Make the request 52 | request = self.api_url % (endpoint, query) 53 | 54 | # Send the request and get the response 55 | # Get the results from cache if available 56 | response = cache.get(client.request, 24, request) 57 | 58 | # Retrun the result as a dictionary 59 | return json.loads(response) 60 | except: 61 | pass 62 | 63 | return {} 64 | 65 | 66 | def showLookup(self, type, id): 67 | try: 68 | result = self.request('lookup/shows', {type: id}) 69 | 70 | # Storing the show id locally 71 | if ('id' in result): 72 | self.show_id = result['id'] 73 | 74 | return result 75 | except: 76 | pass 77 | 78 | return {} 79 | 80 | 81 | def shows(self, show_id = None, embed = None): 82 | try: 83 | if (not self.showID(show_id)): 84 | raise Exception() 85 | 86 | result = self.request('shows/%d' % self.show_id) 87 | 88 | # Storing the show id locally 89 | if ('id' in result): 90 | self.show_id = result['id'] 91 | 92 | return result 93 | except: 94 | pass 95 | 96 | return {} 97 | 98 | 99 | def showSeasons(self, show_id = None): 100 | try: 101 | if (not self.showID(show_id)): 102 | raise Exception() 103 | 104 | result = self.request('shows/%d/seasons' % int( self.show_id )) 105 | 106 | if (len(result) > 0 and 'id' in result[0]): 107 | return result 108 | except: 109 | pass 110 | 111 | return [] 112 | 113 | 114 | def showSeasonList(self, show_id): 115 | return {} 116 | 117 | 118 | def showEpisodeList(self, show_id = None, specials = False): 119 | try: 120 | if (not self.showID(show_id)): 121 | raise Exception() 122 | 123 | result = self.request('shows/%d/episodes' % int( self.show_id ), 'specials=1' if specials else '') 124 | 125 | if (len(result) > 0 and 'id' in result[0]): 126 | return result 127 | except: 128 | pass 129 | 130 | return [] 131 | 132 | 133 | def episodeAbsoluteNumber(self, thetvdb, season, episode): 134 | try: 135 | url = 'http://thetvdb.com/api/%s/series/%s/default/%01d/%01d' % ('MUQ2MkYyRjkwMDMwQzQ0NA=='.decode('base64'), thetvdb, int(season), int(episode)) 136 | return int(client.parseDOM(client.request(url), 'absolute_number')[0]) 137 | except: 138 | pass 139 | 140 | return episode 141 | 142 | 143 | def getTVShowTranslation(self, thetvdb, lang): 144 | try: 145 | url = 'http://thetvdb.com/api/%s/series/%s/%s.xml' % ('MUQ2MkYyRjkwMDMwQzQ0NA=='.decode('base64'), thetvdb, lang) 146 | r = client.request(url) 147 | title = client.parseDOM(r, 'SeriesName')[0] 148 | title = client.replaceHTMLCodes(title) 149 | title = title.encode('utf-8') 150 | 151 | return title 152 | except: 153 | pass 154 | 155 | 156 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | import json, re 23 | 24 | 25 | def json_load_as_str(file_handle): 26 | return byteify(json.load(file_handle, object_hook=byteify), ignore_dicts=True) 27 | 28 | 29 | def json_loads_as_str(json_text): 30 | return byteify(json.loads(json_text, object_hook=byteify), ignore_dicts=True) 31 | 32 | 33 | def byteify(data, ignore_dicts=False): 34 | if isinstance(data, unicode): 35 | return data.encode('utf-8') 36 | if isinstance(data, list): 37 | return [byteify(item, ignore_dicts=True) for item in data] 38 | if isinstance(data, dict) and not ignore_dicts: 39 | return dict([(byteify(key, ignore_dicts=True), byteify(value, ignore_dicts=True)) for key, value in data.iteritems()]) 40 | return data 41 | 42 | def title_key(title): 43 | try: 44 | if title is None: title = '' 45 | articles_en = ['the', 'a', 'an'] 46 | articles_de = ['der', 'die', 'das'] 47 | articles = articles_en + articles_de 48 | 49 | match = re.match('^((\w+)\s+)', title.lower()) 50 | if match and match.group(2) in articles: 51 | offset = len(match.group(1)) 52 | else: 53 | offset = 0 54 | 55 | return title[offset:] 56 | except: 57 | return title 58 | -------------------------------------------------------------------------------- /lib/openscrapers/modules/workers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | OpenScrapers Module 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | """ 18 | 19 | # Addon Name: OpenScrapers Module 20 | # Addon id: script.module.openscrapers 21 | 22 | import threading 23 | 24 | 25 | class Thread(threading.Thread): 26 | def __init__(self, target, *args): 27 | self._target = target 28 | self._args = args 29 | threading.Thread.__init__(self) 30 | def run(self): 31 | self._target(*self._args) 32 | 33 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/cine.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import json 25 | import re 26 | import urllib 27 | import urlparse 28 | 29 | from openscrapers.modules import client 30 | from openscrapers.modules import source_utils 31 | 32 | 33 | class source: 34 | def __init__(self): 35 | self.priority = 1 36 | self.language = ['de'] 37 | self.domains = ['cine.to'] 38 | self.base_link = 'https://cine.to' 39 | self.request_link = '/request/links' 40 | self.out_link = '/out/%s' 41 | 42 | def movie(self, imdb, title, localtitle, aliases, year): 43 | try: 44 | return urllib.urlencode({'imdb': imdb}) 45 | except: 46 | return 47 | 48 | def sources(self, url, hostDict, hostprDict): 49 | sources = [] 50 | 51 | try: 52 | if url == None: 53 | return sources 54 | 55 | data = urlparse.parse_qs(url) 56 | data = dict([(i, data[i][0]) if data[i] else (i, '') for i in data]) 57 | data = urllib.urlencode({'ID': re.sub('[^0-9]', '', str(data['imdb'])), 'lang': 'de'}) 58 | 59 | data = client.request(urlparse.urljoin(self.base_link, self.request_link), post=data, XHR=True) 60 | data = json.loads(data) 61 | data = [(i, data['links'][i]) for i in data['links'] if 'links' in data] 62 | data = [(i[0], i[1][0], (i[1][1:])) for i in data] 63 | 64 | for hoster, quli, links in data: 65 | valid, hoster = source_utils.is_host_valid(hoster, hostDict) 66 | if not valid: continue 67 | 68 | for link in links: 69 | try: sources.append({'source': hoster, 'quality': 'SD', 'language': 'de', 'url': self.out_link % link, 'direct': False, 'debridonly': False}) 70 | except: pass 71 | 72 | return sources 73 | except: 74 | return sources 75 | 76 | def resolve(self, url): 77 | try: 78 | url = urlparse.urljoin(self.base_link, url) 79 | url = client.request(url, output='geturl') 80 | if self.out_link not in url: 81 | return url 82 | except: 83 | return 84 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/ddl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import json 25 | import re 26 | import urllib 27 | import urlparse 28 | 29 | from openscrapers.modules import client 30 | from openscrapers.modules import source_utils 31 | 32 | 33 | class source: 34 | def __init__(self): 35 | self.priority = 1 36 | self.language = ['de'] 37 | self.domains = ['de.ddl.me'] 38 | self.base_link = 'http://de.ddl.me' 39 | self.search_link = '/search_99/?q=%s' 40 | 41 | def movie(self, imdb, title, localtitle, aliases, year): 42 | try: 43 | url = self.__get_direct_url(imdb) 44 | if not url: return 45 | return urllib.urlencode({'url': url}) 46 | except: 47 | return 48 | 49 | def tvshow(self, imdb, tvdb, tvshowtitle, localtvshowtitle, aliases, year): 50 | try: 51 | return self.__get_direct_url(imdb) 52 | except: 53 | return 54 | 55 | def episode(self, url, imdb, tvdb, title, premiered, season, episode): 56 | try: 57 | if url == None: return 58 | 59 | j = self.__get_json(url) 60 | 61 | if not j: return 62 | 63 | j = [v['info'] for k, v in j.items()] 64 | j = [(i['nr'], i['staffel'], i['sid']) for i in j] 65 | j = [(i[2]) for i in j if int(i[0]) == int(episode) and int(i[1]) == int(season)][0] 66 | return urllib.urlencode({'url': url, 'sid': j}) 67 | except: 68 | return 69 | 70 | def sources(self, url, hostDict, hostprDict): 71 | sources = [] 72 | 73 | try: 74 | if url == None: 75 | return sources 76 | 77 | data = urlparse.parse_qs(url) 78 | data = dict([(i, data[i][0]) if data[i] else (i, '') for i in data]) 79 | 80 | j = self.__get_json(data['url']) 81 | 82 | if not j: return 83 | 84 | sid = data['sid'] if 'sid' in data else j.keys()[0] 85 | pcnt = int(j[sid]['1']) if '1' in j[sid] else 1 86 | 87 | for jHoster in j[sid]['links']: 88 | jLinks = [i[3] for i in j[sid]['links'][jHoster] if i[5] == 'stream'] 89 | if len(jLinks) < pcnt: continue 90 | 91 | h_url = jLinks[0] 92 | valid, hoster = source_utils.is_host_valid(h_url, hostDict) 93 | if not valid: continue 94 | 95 | h_url = h_url if pcnt == 1 else 'stack://' + ' , '.join(jLinks) 96 | 97 | try: sources.append({'source': hoster, 'quality': 'SD', 'language': 'de', 'info' : '' if pcnt == 1 else 'multi-part', 'url': h_url, 'direct': False, 'debridonly': False}) 98 | except: pass 99 | 100 | return sources 101 | except: 102 | return sources 103 | 104 | def resolve(self, url): 105 | return url 106 | 107 | def __get_direct_url(self, imdb): 108 | try: 109 | query = urlparse.urljoin(self.base_link, self.search_link % imdb) 110 | r = client.request(query, output='geturl') 111 | 112 | if self.search_link in r: return 113 | return r 114 | except: 115 | return 116 | 117 | def __get_json(self, url): 118 | try: 119 | result = client.request(url) 120 | result = re.compile('var\s+subcats\s+=\s*(.*?);').findall(result)[0] 121 | return json.loads(result) 122 | except: 123 | return 124 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/horrorkino.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import re 25 | import urlparse 26 | 27 | from openscrapers.modules import cleantitle 28 | from openscrapers.modules import client 29 | from openscrapers.modules import dom_parser 30 | from openscrapers.modules import source_utils 31 | 32 | 33 | class source: 34 | def __init__(self): 35 | self.priority = 1 36 | self.language = ['de'] 37 | self.genre_filter = ['horror'] 38 | self.domains = ['horrorkino.do.am'] 39 | self.base_link = 'http://horrorkino.do.am/' 40 | self.search_link = 'video/shv' 41 | 42 | def movie(self, imdb, title, localtitle, aliases, year): 43 | try: 44 | url = self.__search([localtitle] + source_utils.aliases_to_array(aliases), year) 45 | if not url and title != localtitle: url = self.__search([title] + source_utils.aliases_to_array(aliases), year) 46 | return url 47 | except: 48 | return 49 | 50 | def sources(self, url, hostDict, hostprDict): 51 | sources = [] 52 | 53 | try: 54 | if not url: 55 | return sources 56 | 57 | r = client.request(urlparse.urljoin(self.base_link, url)) 58 | r = re.findall('''vicode\s*=\s*["'](.*?)["'];''', r)[0].decode('string_escape') 59 | r = dom_parser.parse_dom(r, 'iframe', req='src') 60 | r = [i.attrs['src'] for i in r] 61 | 62 | for i in r: 63 | valid, host = source_utils.is_host_valid(i, hostDict) 64 | if not valid: continue 65 | 66 | sources.append({'source': host, 'quality': 'SD', 'language': 'de', 'url': i, 'direct': False, 'debridonly': False, 'checkquality': True}) 67 | 68 | return sources 69 | except: 70 | return sources 71 | 72 | def resolve(self, url): 73 | return url 74 | 75 | def __search(self, titles, year): 76 | try: 77 | t = [cleantitle.get(i) for i in set(titles) if i] 78 | y = ['%s' % str(year), '%s' % str(int(year) + 1), '%s' % str(int(year) - 1), '0'] 79 | 80 | r = client.request(urlparse.urljoin(self.base_link, self.search_link), post={'query': cleantitle.query(titles[0])}) 81 | 82 | r = dom_parser.parse_dom(r, 'li', attrs={'class': 'entTd'}) 83 | r = dom_parser.parse_dom(r, 'div', attrs={'class': 've-screen'}, req='title') 84 | r = [(dom_parser.parse_dom(i, 'a', req='href'), i.attrs['title'].split(' - ')[0]) for i in r] 85 | r = [(i[0][0].attrs['href'], i[1], re.findall('(.+?) \(*(\d{4})', i[1])) for i in r] 86 | r = [(i[0], i[2][0][0] if len(i[2]) > 0 else i[1], i[2][0][1] if len(i[2]) > 0 else '0') for i in r] 87 | r = sorted(r, key=lambda i: int(i[2]), reverse=True) # with year > no year 88 | r = [i[0] for i in r if cleantitle.get(i[1]) in t and i[2] in y][0] 89 | 90 | return source_utils.strip_domain(r) 91 | except: 92 | return 93 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/movie2k-ac.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import re 25 | import urllib 26 | import urlparse 27 | 28 | from openscrapers.modules import cleantitle 29 | from openscrapers.modules import client 30 | from openscrapers.modules import source_utils 31 | from openscrapers.modules import dom_parser 32 | 33 | 34 | class source: 35 | def __init__(self): 36 | self.priority = 1 37 | self.language = ['de'] 38 | self.domains = ['movie2k.ac'] 39 | self.base_link = 'http://www.movie2k.ac' 40 | self.search_link = '/search/%s' 41 | 42 | def movie(self, imdb, title, localtitle, aliases, year): 43 | try: 44 | url = self.__search([localtitle] + source_utils.aliases_to_array(aliases)) 45 | if not url and title != localtitle: url = self.__search([title] + source_utils.aliases_to_array(aliases)) 46 | return url 47 | except: 48 | return 49 | 50 | def sources(self, url, hostDict, hostprDict): 51 | sources = [] 52 | 53 | try: 54 | if not url: 55 | return sources 56 | 57 | query = urlparse.urljoin(self.base_link, url) 58 | r = client.request(query) 59 | 60 | r = dom_parser.parse_dom(r, 'div', attrs={'id': 'tab-plot_german'}) 61 | r = dom_parser.parse_dom(r, 'tbody') 62 | r = dom_parser.parse_dom(r, 'tr') 63 | 64 | for i in r: 65 | if re.search('(?<=">)(\n.*?)(?=<\/a>)', i[1]).group().strip(): 66 | hoster = re.search('(?<=">)(\n.*?)(?=<\/a>)', i[1]).group().strip() 67 | link = re.search('(?<=href=\")(.*?)(?=\")', i[1]).group() 68 | rel = re.search('(?<=oddCell qualityCell">)(\n.*?)(?=<\/td>)', i[1]).group().strip() 69 | quality, info = source_utils.get_release_quality(rel) 70 | if not quality: 71 | quality = 'SD' 72 | 73 | valid, hoster = source_utils.is_host_valid(hoster, hostDict) 74 | if not valid: continue 75 | 76 | sources.append({'source': hoster, 'quality': quality, 'language': 'de', 'url': link, 'direct': False, 'debridonly': False}) 77 | 78 | return sources 79 | except: 80 | return sources 81 | 82 | def resolve(self, url): 83 | return url 84 | 85 | def __search(self, titles): 86 | try: 87 | query = self.search_link % (urllib.quote_plus(urllib.quote_plus(cleantitle.query(titles[0])))) 88 | query = urlparse.urljoin(self.base_link, query) 89 | 90 | t = [cleantitle.get(i) for i in set(titles) if i] 91 | 92 | r = client.request(query) 93 | 94 | r = dom_parser.parse_dom(r, 'ul', attrs={'class': 'coverBox'}) 95 | r = dom_parser.parse_dom(r, 'li') 96 | r = dom_parser.parse_dom(r, 'span', attrs={'class': 'name'}) 97 | r = dom_parser.parse_dom(r, 'a') 98 | 99 | title = r[0][1] 100 | title = cleantitle.get(title) 101 | 102 | if title in t: 103 | return source_utils.strip_domain(r[0][0]['href']) 104 | else: 105 | return 106 | except: 107 | return 108 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/netzkino.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import json 25 | import re 26 | import urllib 27 | import urlparse 28 | 29 | from openscrapers.modules import cleantitle 30 | from openscrapers.modules import client 31 | from openscrapers.modules import source_utils 32 | 33 | 34 | class source: 35 | def __init__(self): 36 | self.priority = 1 37 | self.language = ['de'] 38 | self.domains = ['netzkino.de'] 39 | self.base_link = 'http://netzkino.de' 40 | self.conf_link = '/adconf/android-new.php' 41 | self.search_link = 'http://api.netzkino.de.simplecache.net/capi-2.0a/search?q=%s&d=www&l=de-DE&v=unknown-debugBuild' 42 | 43 | def movie(self, imdb, title, localtitle, aliases, year): 44 | try: 45 | url = self.__search([localtitle] + source_utils.aliases_to_array(aliases), imdb, year) 46 | if not url and title != localtitle: url = self.__search([title] + source_utils.aliases_to_array(aliases), imdb, year) 47 | return url 48 | except: 49 | return 50 | 51 | def sources(self, url, hostDict, hostprDict): 52 | sources = [] 53 | 54 | try: 55 | if not url: 56 | return sources 57 | 58 | r = client.request(urlparse.urljoin(self.base_link, self.conf_link), XHR=True) 59 | r = json.loads(r).get('streamer') 60 | r = client.request(r + '%s.mp4/master.m3u8' % url, XHR=True) 61 | 62 | r = re.findall('RESOLUTION\s*=\s*\d+x(\d+).*?\n(http.*?)(?:\n|$)', r, re.IGNORECASE) 63 | r = [(source_utils.label_to_quality(i[0]), i[1]) for i in r] 64 | 65 | for quality, link in r: 66 | sources.append({'source': 'CDN', 'quality': quality, 'language': 'de', 'url': link, 'direct': True, 'debridonly': False}) 67 | 68 | return sources 69 | except: 70 | return sources 71 | 72 | def resolve(self, url): 73 | return url 74 | 75 | def __search(self, titles, imdb, year): 76 | try: 77 | query = self.search_link % (urllib.quote_plus(cleantitle.query(titles[0]))) 78 | query = urlparse.urljoin(self.base_link, query) 79 | 80 | t = [cleantitle.get(i) for i in set(titles) if i] 81 | y = ['%s' % str(year), '%s' % str(int(year) + 1), '%s' % str(int(year) - 1), '0'] 82 | 83 | r = client.request(query, XHR=True) 84 | r = json.loads(r) 85 | 86 | r = [(i.get('title'), i.get('custom_fields', {})) for i in r.get('posts', [])] 87 | r = [(i[0], i[1]) for i in r if i[0] and i[1]] 88 | r = [(i[0], i[1].get('Streaming', ['']), i[1].get('Jahr', ['0']), i[1].get('IMDb-Link', [''])) for i in r if i] 89 | r = [(i[0], i[1][0], i[2][0], re.findall('.+?(tt\d+).*?', i[3][0])) for i in r if i[0] and i[1] and i[2] and i[3]] 90 | r = [i[1] for i in r if imdb in i[3] or (cleantitle.get(i[0]) in t and i[2] in y)][0] 91 | 92 | return source_utils.strip_domain(r) 93 | except: 94 | return 95 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/de/video4k.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ####################################################################### 12 | # ---------------------------------------------------------------------------- 13 | # "THE BEER-WARE LICENSE" (Revision 42): 14 | # @Daddy_Blamo wrote this file. As long as you retain this notice you 15 | # can do whatever you want with this stuff. If we meet some day, and you think 16 | # this stuff is worth it, you can buy me a beer in return. - Muad'Dib 17 | # ---------------------------------------------------------------------------- 18 | ####################################################################### 19 | 20 | # Addon Name: Placenta 21 | # Addon id: plugin.video.placenta 22 | # Addon Provider: Mr.Blamo 23 | 24 | import json 25 | import re 26 | import urllib 27 | import urlparse 28 | 29 | from openscrapers.modules import client 30 | from openscrapers.modules import source_utils 31 | 32 | 33 | class source: 34 | def __init__(self): 35 | self.priority = 1 36 | self.language = ['de'] 37 | self.domains = ['video4k.to'] 38 | self.base_link = 'http://video4k.to' 39 | self.request_link = '/request' 40 | 41 | def movie(self, imdb, title, localtitle, aliases, year): 42 | try: 43 | return urllib.urlencode({'mID': re.sub('[^0-9]', '', imdb)}) 44 | except: 45 | return 46 | 47 | def tvshow(self, imdb, tvdb, tvshowtitle, localtvshowtitle, aliases, year): 48 | try: 49 | return urllib.urlencode({'mID': re.sub('[^0-9]', '', imdb)}) 50 | except: 51 | return 52 | 53 | def episode(self, url, imdb, tvdb, title, premiered, season, episode): 54 | try: 55 | if url == None: 56 | return 57 | 58 | return urllib.urlencode({'mID': re.sub('[^0-9]', '', imdb), 'season': season, 'episode': episode}) 59 | except: 60 | return 61 | 62 | def sources(self, url, hostDict, hostprDict): 63 | sources = [] 64 | 65 | try: 66 | if url == None: 67 | return sources 68 | 69 | data = urlparse.parse_qs(url) 70 | data = dict([(i, data[i][0]) if data[i] else (i, '') for i in data]) 71 | data.update({'raw': 'true', 'language': 'de'}) 72 | data = urllib.urlencode(data) 73 | data = client.request(urlparse.urljoin(self.base_link, self.request_link), post=data) 74 | data = json.loads(data) 75 | data = [i[1] for i in data[1].items()] 76 | data = [(i['name'].lower(), i['links']) for i in data] 77 | 78 | for host, links in data: 79 | valid, host = source_utils.is_host_valid(host, hostDict) 80 | if not valid: continue 81 | 82 | for link in links: 83 | try:sources.append({'source': host, 'quality': 'SD', 'language': 'de', 'url': link['URL'], 'direct': False, 'debridonly': False}) 84 | except: pass 85 | 86 | return sources 87 | except: 88 | return sources 89 | 90 | def resolve(self, url): 91 | return url 92 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/en/0123putlocker.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | # -Cleaned and Checked on 12-03-2018 by JewBMX in Scrubs. 3 | 4 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 5 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 6 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 7 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 8 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 9 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 10 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 11 | 12 | import base64 13 | import re 14 | 15 | from openscrapers.modules import cleantitle, cfscrape 16 | 17 | 18 | class source: 19 | def __init__(self): 20 | self.priority = 1 21 | self.language = ['en'] 22 | self.domains = ['0123putlocker.com'] 23 | self.base_link = 'http://0123putlocker.com' 24 | self.search_link = '/search-movies/%s.html' 25 | self.scraper = cfscrape.create_scraper() 26 | 27 | 28 | def tvshow(self, imdb, tvdb, tvshowtitle, localtvshowtitle, aliases, year): 29 | try: 30 | url = cleantitle.geturl(tvshowtitle) 31 | url = url.replace('-','+') 32 | return url 33 | except: 34 | return 35 | 36 | 37 | def episode(self, url, imdb, tvdb, title, premiered, season, episode): 38 | try: 39 | if not url: return 40 | query = url + '+season+' + season 41 | find = query.replace('+','-') 42 | url = self.base_link + self.search_link % query 43 | r = self.scraper.get(url).content 44 | match = re.compile('' + episode + '').findall(r) 49 | for url in match: 50 | return url 51 | except: 52 | return 53 | 54 | 55 | def sources(self, url, hostDict, hostprDict): 56 | try: 57 | sources = [] 58 | r = self.scraper.get(url).content 59 | try: 60 | match = re.compile('

').findall(r) 61 | for host, url in match: 62 | if host == 'internet': pass 63 | else: sources.append({'source': host,'quality': 'SD','language': 'en','url': url,'direct': False,'debridonly': False}) 64 | except: 65 | return 66 | except Exception: 67 | return 68 | return sources 69 | 70 | 71 | def resolve(self, url): 72 | r = self.scraper.get(url).content 73 | match = re.compile('decode\("(.+?)"').findall(r) 74 | for info in match: 75 | info = base64.b64decode(info) 76 | match = re.compile('src="(.+?)"').findall(info) 77 | for url in match: 78 | return url 79 | 80 | -------------------------------------------------------------------------------- /lib/openscrapers/sources_openscrapers/en/Hdmto.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | # ..#######.########.#######.##....#..######..######.########....###...########.#######.########..######. 4 | # .##.....#.##.....#.##......###...#.##....#.##....#.##.....#...##.##..##.....#.##......##.....#.##....## 5 | # .##.....#.##.....#.##......####..#.##......##......##.....#..##...##.##.....#.##......##.....#.##...... 6 | # .##.....#.########.######..##.##.#..######.##......########.##.....#.########.######..########..######. 7 | # .##.....#.##.......##......##..###.......#.##......##...##..########.##.......##......##...##........## 8 | # .##.....#.##.......##......##...##.##....#.##....#.##....##.##.....#.##.......##......##....##.##....## 9 | # ..#######.##.......#######.##....#..######..######.##.....#.##.....#.##.......#######.##.....#..######. 10 | 11 | ''' 12 | hdmto scraper for Exodus forks. 13 | Nov 9 2018 - Checked 14 | 15 | Updated and refactored by someone. 16 | Originally created by others. 17 | ''' 18 | import re 19 | 20 | from openscrapers.modules import cfscrape 21 | from openscrapers.modules import cleantitle 22 | 23 | 24 | class source: 25 | def __init__(self): 26 | self.priority = 1 27 | self.language = ['en'] 28 | self.domains = ['hdm.to'] 29 | self.base_link = 'https://hdm.to' 30 | self.scraper = cfscrape.create_scraper() 31 | 32 | def movie(self, imdb, title, localtitle, aliases, year): 33 | try: 34 | url = cleantitle.geturl(title) 35 | return url 36 | except: 37 | return 38 | 39 | def sources(self, url, hostDict, hostprDict): 40 | try: 41 | sources = [] 42 | url = '%s/%s/' % (self.base_link,url) 43 | r = self.scraper.get(url).content 44 | try: 45 | match = re.compile('