From 16af85004c84d0d6c626b4f8424ce9647669a0c1 Mon Sep 17 00:00:00 2001 From: RaNaN Date: Sun, 9 Jun 2013 18:10:22 +0200 Subject: moved everything from module to pyload --- pyload/plugins/Account.py | 295 ++++++++++++++++ pyload/plugins/Addon.py | 205 +++++++++++ pyload/plugins/Base.py | 343 +++++++++++++++++++ pyload/plugins/Crypter.py | 271 +++++++++++++++ pyload/plugins/Hoster.py | 400 ++++++++++++++++++++++ pyload/plugins/MultiHoster.py | 73 ++++ pyload/plugins/ReCaptcha.py | 22 ++ pyload/plugins/__init__.py | 0 pyload/plugins/accounts/AlldebridCom.py | 49 +++ pyload/plugins/accounts/BayfilesCom.py | 51 +++ pyload/plugins/accounts/BitshareCom.py | 44 +++ pyload/plugins/accounts/BoltsharingCom.py | 12 + pyload/plugins/accounts/CramitIn.py | 12 + pyload/plugins/accounts/CyberlockerCh.py | 31 ++ pyload/plugins/accounts/CzshareCom.py | 57 ++++ pyload/plugins/accounts/DdlstorageCom.py | 12 + pyload/plugins/accounts/DebridItaliaCom.py | 50 +++ pyload/plugins/accounts/DepositfilesCom.py | 47 +++ pyload/plugins/accounts/EasybytezCom.py | 73 ++++ pyload/plugins/accounts/EgoFilesCom.py | 40 +++ pyload/plugins/accounts/EuroshareEu.py | 55 +++ pyload/plugins/accounts/FastshareCz.py | 54 +++ pyload/plugins/accounts/FilebeerInfo.py | 57 ++++ pyload/plugins/accounts/FilecloudIo.py | 49 +++ pyload/plugins/accounts/FilefactoryCom.py | 54 +++ pyload/plugins/accounts/FilejungleCom.py | 60 ++++ pyload/plugins/accounts/FilerioCom.py | 12 + pyload/plugins/accounts/FilesMailRu.py | 41 +++ pyload/plugins/accounts/FileserveCom.py | 58 ++++ pyload/plugins/accounts/FourSharedCom.py | 48 +++ pyload/plugins/accounts/FreakshareCom.py | 51 +++ pyload/plugins/accounts/FshareVn.py | 62 ++++ pyload/plugins/accounts/Ftp.py | 13 + pyload/plugins/accounts/HellshareCz.py | 87 +++++ pyload/plugins/accounts/HellspyCz.py | 70 ++++ pyload/plugins/accounts/HotfileCom.py | 86 +++++ pyload/plugins/accounts/Http.py | 13 + pyload/plugins/accounts/MegasharesCom.py | 42 +++ pyload/plugins/accounts/MultiDebridCom.py | 47 +++ pyload/plugins/accounts/MultishareCz.py | 58 ++++ pyload/plugins/accounts/NetloadIn.py | 49 +++ pyload/plugins/accounts/Premium4Me.py | 27 ++ pyload/plugins/accounts/PremiumizeMe.py | 44 +++ pyload/plugins/accounts/QuickshareCz.py | 53 +++ pyload/plugins/accounts/RapidgatorNet.py | 74 ++++ pyload/plugins/accounts/RapidshareCom.py | 68 ++++ pyload/plugins/accounts/RarefileNet.py | 12 + pyload/plugins/accounts/RealdebridCom.py | 35 ++ pyload/plugins/accounts/RehostTo.py | 37 ++ pyload/plugins/accounts/ReloadCc.py | 73 ++++ pyload/plugins/accounts/RyushareCom.py | 18 + pyload/plugins/accounts/Share76Com.py | 11 + pyload/plugins/accounts/ShareFilesCo.py | 12 + pyload/plugins/accounts/ShareRapidCom.py | 47 +++ pyload/plugins/accounts/ShareonlineBiz.py | 56 +++ pyload/plugins/accounts/SpeedLoadOrg.py | 12 + pyload/plugins/accounts/StahnuTo.py | 49 +++ pyload/plugins/accounts/TurbobitNet.py | 56 +++ pyload/plugins/accounts/UlozTo.py | 36 ++ pyload/plugins/accounts/UploadedTo.py | 65 ++++ pyload/plugins/accounts/UploadheroCom.py | 35 ++ pyload/plugins/accounts/UploadingCom.py | 52 +++ pyload/plugins/accounts/UploadstationCom.py | 13 + pyload/plugins/accounts/UptoboxCom.py | 12 + pyload/plugins/accounts/WarserverCz.py | 70 ++++ pyload/plugins/accounts/WuploadCom.py | 47 +++ pyload/plugins/accounts/X7To.py | 66 ++++ pyload/plugins/accounts/YibaishiwuCom.py | 51 +++ pyload/plugins/accounts/ZeveraCom.py | 49 +++ pyload/plugins/accounts/__init__.py | 0 pyload/plugins/addons/AlldebridCom.py | 28 ++ pyload/plugins/addons/BypassCaptcha.py | 143 ++++++++ pyload/plugins/addons/CaptchaBrotherhood.py | 169 ++++++++++ pyload/plugins/addons/CaptchaTrader.py | 159 +++++++++ pyload/plugins/addons/Checksum.py | 169 ++++++++++ pyload/plugins/addons/ClickAndLoad.py | 89 +++++ pyload/plugins/addons/DeathByCaptcha.py | 210 ++++++++++++ pyload/plugins/addons/DebridItaliaCom.py | 41 +++ pyload/plugins/addons/DeleteFinished.py | 86 +++++ pyload/plugins/addons/DownloadScheduler.py | 86 +++++ pyload/plugins/addons/EasybytezCom.py | 31 ++ pyload/plugins/addons/Ev0InFetcher.py | 87 +++++ pyload/plugins/addons/ExpertDecoders.py | 112 ++++++ pyload/plugins/addons/ExternalScripts.py | 118 +++++++ pyload/plugins/addons/ExtractArchive.py | 312 +++++++++++++++++ pyload/plugins/addons/HotFolder.py | 85 +++++ pyload/plugins/addons/IRCInterface.py | 431 ++++++++++++++++++++++++ pyload/plugins/addons/ImageTyperz.py | 160 +++++++++ pyload/plugins/addons/LinkdecrypterCom.py | 59 ++++ pyload/plugins/addons/MergeFiles.py | 94 ++++++ pyload/plugins/addons/MultiDebridCom.py | 42 +++ pyload/plugins/addons/MultiHome.py | 82 +++++ pyload/plugins/addons/MultiHoster.py | 102 ++++++ pyload/plugins/addons/MultishareCz.py | 23 ++ pyload/plugins/addons/Premium4Me.py | 33 ++ pyload/plugins/addons/PremiumizeMe.py | 50 +++ pyload/plugins/addons/RealdebridCom.py | 25 ++ pyload/plugins/addons/RehostTo.py | 41 +++ pyload/plugins/addons/RestartFailed.py | 124 +++++++ pyload/plugins/addons/UnSkipOnFail.py | 97 ++++++ pyload/plugins/addons/UpdateManager.py | 201 +++++++++++ pyload/plugins/addons/XFileSharingPro.py | 70 ++++ pyload/plugins/addons/XMPPInterface.py | 276 +++++++++++++++ pyload/plugins/addons/ZeveraCom.py | 19 ++ pyload/plugins/addons/__init__.py | 0 pyload/plugins/crypter/C1neonCom.py | 133 ++++++++ pyload/plugins/crypter/CCF.py | 42 +++ pyload/plugins/crypter/CrockoComFolder.py | 14 + pyload/plugins/crypter/CryptItCom.py | 38 +++ pyload/plugins/crypter/CzshareComFolder.py | 30 ++ pyload/plugins/crypter/DDLMusicOrg.py | 42 +++ pyload/plugins/crypter/DataHuFolder.py | 55 +++ pyload/plugins/crypter/DdlstorageComFolder.py | 32 ++ pyload/plugins/crypter/DepositfilesComFolder.py | 14 + pyload/plugins/crypter/Dereferer.py | 34 ++ pyload/plugins/crypter/DontKnowMe.py | 21 ++ pyload/plugins/crypter/DownloadVimeoCom.py | 30 ++ pyload/plugins/crypter/DuckCryptInfo.py | 58 ++++ pyload/plugins/crypter/EasybytezComFolder.py | 60 ++++ pyload/plugins/crypter/EmbeduploadCom.py | 54 +++ pyload/plugins/crypter/FilebeerInfoFolder.py | 35 ++ pyload/plugins/crypter/FilefactoryComFolder.py | 44 +++ pyload/plugins/crypter/FileserveComFolder.py | 32 ++ pyload/plugins/crypter/FourChanOrg.py | 25 ++ pyload/plugins/crypter/FshareVnFolder.py | 14 + pyload/plugins/crypter/GooGl.py | 41 +++ pyload/plugins/crypter/HoerbuchIn.py | 55 +++ pyload/plugins/crypter/HotfileFolderCom.py | 29 ++ pyload/plugins/crypter/ILoadTo.py | 62 ++++ pyload/plugins/crypter/LetitbitNetFolder.py | 33 ++ pyload/plugins/crypter/LinkList.py | 55 +++ pyload/plugins/crypter/LinkSaveIn.py | 227 +++++++++++++ pyload/plugins/crypter/LinkdecrypterCom.py | 100 ++++++ pyload/plugins/crypter/LixIn.py | 60 ++++ pyload/plugins/crypter/LofCc.py | 49 +++ pyload/plugins/crypter/MBLinkInfo.py | 27 ++ pyload/plugins/crypter/MediafireComFolder.py | 55 +++ pyload/plugins/crypter/Movie2kTo.py | 151 +++++++++ pyload/plugins/crypter/MultiloadCz.py | 41 +++ pyload/plugins/crypter/MultiuploadCom.py | 58 ++++ pyload/plugins/crypter/NCryptIn.py | 251 ++++++++++++++ pyload/plugins/crypter/NetfolderIn.py | 71 ++++ pyload/plugins/crypter/OneKhDe.py | 36 ++ pyload/plugins/crypter/OronComFolder.py | 46 +++ pyload/plugins/crypter/QuickshareCzFolder.py | 30 ++ pyload/plugins/crypter/RSDF.py | 49 +++ pyload/plugins/crypter/RSLayerCom.py | 49 +++ pyload/plugins/crypter/RelinkUs.py | 264 +++++++++++++++ pyload/plugins/crypter/SecuredIn.py | 334 ++++++++++++++++++ pyload/plugins/crypter/SerienjunkiesOrg.py | 321 ++++++++++++++++++ pyload/plugins/crypter/ShareLinksBiz.py | 269 +++++++++++++++ pyload/plugins/crypter/ShareRapidComFolder.py | 14 + pyload/plugins/crypter/SpeedLoadOrgFolder.py | 30 ++ pyload/plugins/crypter/StealthTo.py | 45 +++ pyload/plugins/crypter/TrailerzoneInfo.py | 45 +++ pyload/plugins/crypter/UlozToFolder.py | 40 +++ pyload/plugins/crypter/UploadedToFolder.py | 50 +++ pyload/plugins/crypter/WiiReloadedOrg.py | 52 +++ pyload/plugins/crypter/XfilesharingProFolder.py | 34 ++ pyload/plugins/crypter/YoutubeBatch.py | 42 +++ pyload/plugins/crypter/__init__.py | 0 pyload/plugins/hooks/Captcha9kw.py | 162 +++++++++ pyload/plugins/hooks/ReloadCc.py | 65 ++++ pyload/plugins/hoster/ARD.py | 80 +++++ pyload/plugins/hoster/AlldebridCom.py | 84 +++++ pyload/plugins/hoster/BasePlugin.py | 104 ++++++ pyload/plugins/hoster/BayfilesCom.py | 93 +++++ pyload/plugins/hoster/BezvadataCz.py | 94 ++++++ pyload/plugins/hoster/BillionuploadsCom.py | 17 + pyload/plugins/hoster/BitshareCom.py | 179 ++++++++++ pyload/plugins/hoster/BoltsharingCom.py | 15 + pyload/plugins/hoster/CatShareNet.py | 38 +++ pyload/plugins/hoster/ChipDe.py | 24 ++ pyload/plugins/hoster/CloudzerNet.py | 65 ++++ pyload/plugins/hoster/CramitIn.py | 20 ++ pyload/plugins/hoster/CrockoCom.py | 71 ++++ pyload/plugins/hoster/CyberlockerCh.py | 15 + pyload/plugins/hoster/CzshareCom.py | 160 +++++++++ pyload/plugins/hoster/DailymotionCom.py | 47 +++ pyload/plugins/hoster/DataHu.py | 53 +++ pyload/plugins/hoster/DataportCz.py | 68 ++++ pyload/plugins/hoster/DateiTo.py | 94 ++++++ pyload/plugins/hoster/DdlstorageCom.py | 20 ++ pyload/plugins/hoster/DebridItaliaCom.py | 61 ++++ pyload/plugins/hoster/DepositfilesCom.py | 112 ++++++ pyload/plugins/hoster/DlFreeFr.py | 183 ++++++++++ pyload/plugins/hoster/EasybytezCom.py | 47 +++ pyload/plugins/hoster/EdiskCz.py | 62 ++++ pyload/plugins/hoster/EgoFilesCom.py | 103 ++++++ pyload/plugins/hoster/EuroshareEu.py | 74 ++++ pyload/plugins/hoster/ExtabitCom.py | 87 +++++ pyload/plugins/hoster/FastshareCz.py | 96 ++++++ pyload/plugins/hoster/FileApeCom.py | 62 ++++ pyload/plugins/hoster/FilebeerInfo.py | 15 + pyload/plugins/hoster/FilecloudIo.py | 112 ++++++ pyload/plugins/hoster/FilefactoryCom.py | 133 ++++++++ pyload/plugins/hoster/FilejungleCom.py | 38 +++ pyload/plugins/hoster/FilepostCom.py | 135 ++++++++ pyload/plugins/hoster/FilerNet.py | 103 ++++++ pyload/plugins/hoster/FilerioCom.py | 20 ++ pyload/plugins/hoster/FilesMailRu.py | 99 ++++++ pyload/plugins/hoster/FileserveCom.py | 211 ++++++++++++ pyload/plugins/hoster/FileshareInUa.py | 78 +++++ pyload/plugins/hoster/FlyFilesNet.py | 41 +++ pyload/plugins/hoster/FourSharedCom.py | 53 +++ pyload/plugins/hoster/FreakshareCom.py | 167 +++++++++ pyload/plugins/hoster/FreevideoCz.py | 64 ++++ pyload/plugins/hoster/FshareVn.py | 111 ++++++ pyload/plugins/hoster/Ftp.py | 91 +++++ pyload/plugins/hoster/GamefrontCom.py | 80 +++++ pyload/plugins/hoster/GigapetaCom.py | 73 ++++ pyload/plugins/hoster/HellshareCz.py | 56 +++ pyload/plugins/hoster/HellspyCz.py | 70 ++++ pyload/plugins/hoster/HotfileCom.py | 137 ++++++++ pyload/plugins/hoster/IFileWs.py | 20 ++ pyload/plugins/hoster/IcyFilesCom.py | 112 ++++++ pyload/plugins/hoster/IfileIt.py | 74 ++++ pyload/plugins/hoster/IfolderRu.py | 90 +++++ pyload/plugins/hoster/JumbofilesCom.py | 31 ++ pyload/plugins/hoster/LetitbitNet.py | 125 +++++++ pyload/plugins/hoster/LoadTo.py | 83 +++++ pyload/plugins/hoster/LuckyShareNet.py | 72 ++++ pyload/plugins/hoster/MediafireCom.py | 135 ++++++++ pyload/plugins/hoster/MegaNz.py | 125 +++++++ pyload/plugins/hoster/MegasharesCom.py | 108 ++++++ pyload/plugins/hoster/MovReelCom.py | 106 ++++++ pyload/plugins/hoster/MultiDebridCom.py | 57 ++++ pyload/plugins/hoster/MultishareCz.py | 76 +++++ pyload/plugins/hoster/MyvideoDe.py | 43 +++ pyload/plugins/hoster/NarodRu.py | 66 ++++ pyload/plugins/hoster/NetloadIn.py | 252 ++++++++++++++ pyload/plugins/hoster/NovafileCom.py | 24 ++ pyload/plugins/hoster/NowDownloadEu.py | 66 ++++ pyload/plugins/hoster/OneFichierCom.py | 58 ++++ pyload/plugins/hoster/PornhostCom.py | 76 +++++ pyload/plugins/hoster/PornhubCom.py | 83 +++++ pyload/plugins/hoster/Premium4Me.py | 70 ++++ pyload/plugins/hoster/PremiumizeMe.py | 50 +++ pyload/plugins/hoster/PutlockerCom.py | 78 +++++ pyload/plugins/hoster/QuickshareCz.py | 99 ++++++ pyload/plugins/hoster/RapidgatorNet.py | 192 +++++++++++ pyload/plugins/hoster/RapidshareCom.py | 225 +++++++++++++ pyload/plugins/hoster/RarefileNet.py | 34 ++ pyload/plugins/hoster/RealdebridCom.py | 88 +++++ pyload/plugins/hoster/RedtubeCom.py | 56 +++ pyload/plugins/hoster/RehostTo.py | 37 ++ pyload/plugins/hoster/ReloadCc.py | 103 ++++++ pyload/plugins/hoster/RyushareCom.py | 55 +++ pyload/plugins/hoster/SecureUploadEu.py | 18 + pyload/plugins/hoster/SendmywayCom.py | 18 + pyload/plugins/hoster/SendspaceCom.py | 67 ++++ pyload/plugins/hoster/Share4webCom.py | 16 + pyload/plugins/hoster/Share76Com.py | 19 ++ pyload/plugins/hoster/ShareFilesCo.py | 24 ++ pyload/plugins/hoster/ShareRapidCom.py | 104 ++++++ pyload/plugins/hoster/SharebeesCom.py | 19 ++ pyload/plugins/hoster/ShareonlineBiz.py | 203 +++++++++++ pyload/plugins/hoster/ShareplaceCom.py | 84 +++++ pyload/plugins/hoster/ShragleCom.py | 106 ++++++ pyload/plugins/hoster/SpeedLoadOrg.py | 21 ++ pyload/plugins/hoster/SpeedfileCz.py | 65 ++++ pyload/plugins/hoster/StreamCz.py | 76 +++++ pyload/plugins/hoster/TurbobitNet.py | 170 ++++++++++ pyload/plugins/hoster/TurbouploadCom.py | 45 +++ pyload/plugins/hoster/TusfilesNet.py | 18 + pyload/plugins/hoster/TwoSharedCom.py | 33 ++ pyload/plugins/hoster/UlozTo.py | 156 +++++++++ pyload/plugins/hoster/UloziskoSk.py | 75 +++++ pyload/plugins/hoster/UnibytesCom.py | 80 +++++ pyload/plugins/hoster/UploadStationCom.py | 21 ++ pyload/plugins/hoster/UploadedTo.py | 238 +++++++++++++ pyload/plugins/hoster/UploadheroCom.py | 84 +++++ pyload/plugins/hoster/UploadingCom.py | 110 ++++++ pyload/plugins/hoster/UptoboxCom.py | 21 ++ pyload/plugins/hoster/VeehdCom.py | 80 +++++ pyload/plugins/hoster/WarserverCz.py | 70 ++++ pyload/plugins/hoster/WebshareCz.py | 48 +++ pyload/plugins/hoster/WrzucTo.py | 58 ++++ pyload/plugins/hoster/WuploadCom.py | 241 +++++++++++++ pyload/plugins/hoster/X7To.py | 93 +++++ pyload/plugins/hoster/XFileSharingPro.py | 314 +++++++++++++++++ pyload/plugins/hoster/XHamsterCom.py | 120 +++++++ pyload/plugins/hoster/XVideosCom.py | 19 ++ pyload/plugins/hoster/Xdcc.py | 229 +++++++++++++ pyload/plugins/hoster/XvidstageCom.py | 114 +++++++ pyload/plugins/hoster/YibaishiwuCom.py | 54 +++ pyload/plugins/hoster/YoupornCom.py | 56 +++ pyload/plugins/hoster/YourfilesTo.py | 83 +++++ pyload/plugins/hoster/YoutubeCom.py | 164 +++++++++ pyload/plugins/hoster/ZDF.py | 46 +++ pyload/plugins/hoster/ZeveraCom.py | 108 ++++++ pyload/plugins/hoster/ZippyshareCom.py | 187 ++++++++++ pyload/plugins/hoster/__init__.py | 0 pyload/plugins/internal/AbstractExtractor.py | 93 +++++ pyload/plugins/internal/CaptchaService.py | 77 +++++ pyload/plugins/internal/DeadHoster.py | 18 + pyload/plugins/internal/NetloadInOCR.py | 27 ++ pyload/plugins/internal/OCR.py | 314 +++++++++++++++++ pyload/plugins/internal/ShareonlineBizOCR.py | 53 +++ pyload/plugins/internal/SimpleCrypter.py | 68 ++++ pyload/plugins/internal/SimpleHoster.py | 251 ++++++++++++++ pyload/plugins/internal/UnRar.py | 212 ++++++++++++ pyload/plugins/internal/UnZip.py | 49 +++ pyload/plugins/internal/XFSPAccount.py | 79 +++++ pyload/plugins/internal/__init__.py | 0 305 files changed, 24636 insertions(+) create mode 100644 pyload/plugins/Account.py create mode 100644 pyload/plugins/Addon.py create mode 100644 pyload/plugins/Base.py create mode 100644 pyload/plugins/Crypter.py create mode 100644 pyload/plugins/Hoster.py create mode 100644 pyload/plugins/MultiHoster.py create mode 100644 pyload/plugins/ReCaptcha.py create mode 100644 pyload/plugins/__init__.py create mode 100644 pyload/plugins/accounts/AlldebridCom.py create mode 100644 pyload/plugins/accounts/BayfilesCom.py create mode 100644 pyload/plugins/accounts/BitshareCom.py create mode 100644 pyload/plugins/accounts/BoltsharingCom.py create mode 100644 pyload/plugins/accounts/CramitIn.py create mode 100644 pyload/plugins/accounts/CyberlockerCh.py create mode 100644 pyload/plugins/accounts/CzshareCom.py create mode 100644 pyload/plugins/accounts/DdlstorageCom.py create mode 100644 pyload/plugins/accounts/DebridItaliaCom.py create mode 100644 pyload/plugins/accounts/DepositfilesCom.py create mode 100644 pyload/plugins/accounts/EasybytezCom.py create mode 100644 pyload/plugins/accounts/EgoFilesCom.py create mode 100644 pyload/plugins/accounts/EuroshareEu.py create mode 100644 pyload/plugins/accounts/FastshareCz.py create mode 100644 pyload/plugins/accounts/FilebeerInfo.py create mode 100644 pyload/plugins/accounts/FilecloudIo.py create mode 100644 pyload/plugins/accounts/FilefactoryCom.py create mode 100644 pyload/plugins/accounts/FilejungleCom.py create mode 100644 pyload/plugins/accounts/FilerioCom.py create mode 100644 pyload/plugins/accounts/FilesMailRu.py create mode 100644 pyload/plugins/accounts/FileserveCom.py create mode 100644 pyload/plugins/accounts/FourSharedCom.py create mode 100644 pyload/plugins/accounts/FreakshareCom.py create mode 100644 pyload/plugins/accounts/FshareVn.py create mode 100644 pyload/plugins/accounts/Ftp.py create mode 100644 pyload/plugins/accounts/HellshareCz.py create mode 100644 pyload/plugins/accounts/HellspyCz.py create mode 100644 pyload/plugins/accounts/HotfileCom.py create mode 100644 pyload/plugins/accounts/Http.py create mode 100644 pyload/plugins/accounts/MegasharesCom.py create mode 100644 pyload/plugins/accounts/MultiDebridCom.py create mode 100644 pyload/plugins/accounts/MultishareCz.py create mode 100755 pyload/plugins/accounts/NetloadIn.py create mode 100644 pyload/plugins/accounts/Premium4Me.py create mode 100644 pyload/plugins/accounts/PremiumizeMe.py create mode 100644 pyload/plugins/accounts/QuickshareCz.py create mode 100644 pyload/plugins/accounts/RapidgatorNet.py create mode 100644 pyload/plugins/accounts/RapidshareCom.py create mode 100644 pyload/plugins/accounts/RarefileNet.py create mode 100644 pyload/plugins/accounts/RealdebridCom.py create mode 100644 pyload/plugins/accounts/RehostTo.py create mode 100644 pyload/plugins/accounts/ReloadCc.py create mode 100644 pyload/plugins/accounts/RyushareCom.py create mode 100644 pyload/plugins/accounts/Share76Com.py create mode 100644 pyload/plugins/accounts/ShareFilesCo.py create mode 100644 pyload/plugins/accounts/ShareRapidCom.py create mode 100644 pyload/plugins/accounts/ShareonlineBiz.py create mode 100644 pyload/plugins/accounts/SpeedLoadOrg.py create mode 100644 pyload/plugins/accounts/StahnuTo.py create mode 100644 pyload/plugins/accounts/TurbobitNet.py create mode 100644 pyload/plugins/accounts/UlozTo.py create mode 100644 pyload/plugins/accounts/UploadedTo.py create mode 100644 pyload/plugins/accounts/UploadheroCom.py create mode 100644 pyload/plugins/accounts/UploadingCom.py create mode 100644 pyload/plugins/accounts/UploadstationCom.py create mode 100644 pyload/plugins/accounts/UptoboxCom.py create mode 100644 pyload/plugins/accounts/WarserverCz.py create mode 100644 pyload/plugins/accounts/WuploadCom.py create mode 100644 pyload/plugins/accounts/X7To.py create mode 100644 pyload/plugins/accounts/YibaishiwuCom.py create mode 100644 pyload/plugins/accounts/ZeveraCom.py create mode 100644 pyload/plugins/accounts/__init__.py create mode 100644 pyload/plugins/addons/AlldebridCom.py create mode 100644 pyload/plugins/addons/BypassCaptcha.py create mode 100644 pyload/plugins/addons/CaptchaBrotherhood.py create mode 100644 pyload/plugins/addons/CaptchaTrader.py create mode 100644 pyload/plugins/addons/Checksum.py create mode 100644 pyload/plugins/addons/ClickAndLoad.py create mode 100644 pyload/plugins/addons/DeathByCaptcha.py create mode 100644 pyload/plugins/addons/DebridItaliaCom.py create mode 100644 pyload/plugins/addons/DeleteFinished.py create mode 100644 pyload/plugins/addons/DownloadScheduler.py create mode 100644 pyload/plugins/addons/EasybytezCom.py create mode 100644 pyload/plugins/addons/Ev0InFetcher.py create mode 100644 pyload/plugins/addons/ExpertDecoders.py create mode 100644 pyload/plugins/addons/ExternalScripts.py create mode 100644 pyload/plugins/addons/ExtractArchive.py create mode 100644 pyload/plugins/addons/HotFolder.py create mode 100644 pyload/plugins/addons/IRCInterface.py create mode 100644 pyload/plugins/addons/ImageTyperz.py create mode 100644 pyload/plugins/addons/LinkdecrypterCom.py create mode 100644 pyload/plugins/addons/MergeFiles.py create mode 100644 pyload/plugins/addons/MultiDebridCom.py create mode 100644 pyload/plugins/addons/MultiHome.py create mode 100644 pyload/plugins/addons/MultiHoster.py create mode 100644 pyload/plugins/addons/MultishareCz.py create mode 100644 pyload/plugins/addons/Premium4Me.py create mode 100644 pyload/plugins/addons/PremiumizeMe.py create mode 100644 pyload/plugins/addons/RealdebridCom.py create mode 100644 pyload/plugins/addons/RehostTo.py create mode 100644 pyload/plugins/addons/RestartFailed.py create mode 100644 pyload/plugins/addons/UnSkipOnFail.py create mode 100644 pyload/plugins/addons/UpdateManager.py create mode 100644 pyload/plugins/addons/XFileSharingPro.py create mode 100644 pyload/plugins/addons/XMPPInterface.py create mode 100644 pyload/plugins/addons/ZeveraCom.py create mode 100644 pyload/plugins/addons/__init__.py create mode 100644 pyload/plugins/crypter/C1neonCom.py create mode 100644 pyload/plugins/crypter/CCF.py create mode 100644 pyload/plugins/crypter/CrockoComFolder.py create mode 100644 pyload/plugins/crypter/CryptItCom.py create mode 100644 pyload/plugins/crypter/CzshareComFolder.py create mode 100644 pyload/plugins/crypter/DDLMusicOrg.py create mode 100644 pyload/plugins/crypter/DataHuFolder.py create mode 100644 pyload/plugins/crypter/DdlstorageComFolder.py create mode 100644 pyload/plugins/crypter/DepositfilesComFolder.py create mode 100644 pyload/plugins/crypter/Dereferer.py create mode 100644 pyload/plugins/crypter/DontKnowMe.py create mode 100644 pyload/plugins/crypter/DownloadVimeoCom.py create mode 100644 pyload/plugins/crypter/DuckCryptInfo.py create mode 100644 pyload/plugins/crypter/EasybytezComFolder.py create mode 100644 pyload/plugins/crypter/EmbeduploadCom.py create mode 100644 pyload/plugins/crypter/FilebeerInfoFolder.py create mode 100644 pyload/plugins/crypter/FilefactoryComFolder.py create mode 100644 pyload/plugins/crypter/FileserveComFolder.py create mode 100644 pyload/plugins/crypter/FourChanOrg.py create mode 100644 pyload/plugins/crypter/FshareVnFolder.py create mode 100644 pyload/plugins/crypter/GooGl.py create mode 100644 pyload/plugins/crypter/HoerbuchIn.py create mode 100644 pyload/plugins/crypter/HotfileFolderCom.py create mode 100644 pyload/plugins/crypter/ILoadTo.py create mode 100644 pyload/plugins/crypter/LetitbitNetFolder.py create mode 100644 pyload/plugins/crypter/LinkList.py create mode 100644 pyload/plugins/crypter/LinkSaveIn.py create mode 100644 pyload/plugins/crypter/LinkdecrypterCom.py create mode 100644 pyload/plugins/crypter/LixIn.py create mode 100644 pyload/plugins/crypter/LofCc.py create mode 100644 pyload/plugins/crypter/MBLinkInfo.py create mode 100644 pyload/plugins/crypter/MediafireComFolder.py create mode 100644 pyload/plugins/crypter/Movie2kTo.py create mode 100644 pyload/plugins/crypter/MultiloadCz.py create mode 100644 pyload/plugins/crypter/MultiuploadCom.py create mode 100644 pyload/plugins/crypter/NCryptIn.py create mode 100644 pyload/plugins/crypter/NetfolderIn.py create mode 100644 pyload/plugins/crypter/OneKhDe.py create mode 100755 pyload/plugins/crypter/OronComFolder.py create mode 100644 pyload/plugins/crypter/QuickshareCzFolder.py create mode 100644 pyload/plugins/crypter/RSDF.py create mode 100644 pyload/plugins/crypter/RSLayerCom.py create mode 100644 pyload/plugins/crypter/RelinkUs.py create mode 100644 pyload/plugins/crypter/SecuredIn.py create mode 100644 pyload/plugins/crypter/SerienjunkiesOrg.py create mode 100644 pyload/plugins/crypter/ShareLinksBiz.py create mode 100644 pyload/plugins/crypter/ShareRapidComFolder.py create mode 100644 pyload/plugins/crypter/SpeedLoadOrgFolder.py create mode 100644 pyload/plugins/crypter/StealthTo.py create mode 100644 pyload/plugins/crypter/TrailerzoneInfo.py create mode 100644 pyload/plugins/crypter/UlozToFolder.py create mode 100644 pyload/plugins/crypter/UploadedToFolder.py create mode 100644 pyload/plugins/crypter/WiiReloadedOrg.py create mode 100644 pyload/plugins/crypter/XfilesharingProFolder.py create mode 100644 pyload/plugins/crypter/YoutubeBatch.py create mode 100644 pyload/plugins/crypter/__init__.py create mode 100755 pyload/plugins/hooks/Captcha9kw.py create mode 100644 pyload/plugins/hooks/ReloadCc.py create mode 100644 pyload/plugins/hoster/ARD.py create mode 100644 pyload/plugins/hoster/AlldebridCom.py create mode 100644 pyload/plugins/hoster/BasePlugin.py create mode 100644 pyload/plugins/hoster/BayfilesCom.py create mode 100644 pyload/plugins/hoster/BezvadataCz.py create mode 100644 pyload/plugins/hoster/BillionuploadsCom.py create mode 100644 pyload/plugins/hoster/BitshareCom.py create mode 100644 pyload/plugins/hoster/BoltsharingCom.py create mode 100644 pyload/plugins/hoster/CatShareNet.py create mode 100644 pyload/plugins/hoster/ChipDe.py create mode 100644 pyload/plugins/hoster/CloudzerNet.py create mode 100644 pyload/plugins/hoster/CramitIn.py create mode 100644 pyload/plugins/hoster/CrockoCom.py create mode 100644 pyload/plugins/hoster/CyberlockerCh.py create mode 100644 pyload/plugins/hoster/CzshareCom.py create mode 100644 pyload/plugins/hoster/DailymotionCom.py create mode 100644 pyload/plugins/hoster/DataHu.py create mode 100644 pyload/plugins/hoster/DataportCz.py create mode 100644 pyload/plugins/hoster/DateiTo.py create mode 100644 pyload/plugins/hoster/DdlstorageCom.py create mode 100644 pyload/plugins/hoster/DebridItaliaCom.py create mode 100644 pyload/plugins/hoster/DepositfilesCom.py create mode 100644 pyload/plugins/hoster/DlFreeFr.py create mode 100644 pyload/plugins/hoster/EasybytezCom.py create mode 100644 pyload/plugins/hoster/EdiskCz.py create mode 100644 pyload/plugins/hoster/EgoFilesCom.py create mode 100644 pyload/plugins/hoster/EuroshareEu.py create mode 100644 pyload/plugins/hoster/ExtabitCom.py create mode 100644 pyload/plugins/hoster/FastshareCz.py create mode 100644 pyload/plugins/hoster/FileApeCom.py create mode 100644 pyload/plugins/hoster/FilebeerInfo.py create mode 100644 pyload/plugins/hoster/FilecloudIo.py create mode 100644 pyload/plugins/hoster/FilefactoryCom.py create mode 100644 pyload/plugins/hoster/FilejungleCom.py create mode 100644 pyload/plugins/hoster/FilepostCom.py create mode 100644 pyload/plugins/hoster/FilerNet.py create mode 100644 pyload/plugins/hoster/FilerioCom.py create mode 100644 pyload/plugins/hoster/FilesMailRu.py create mode 100644 pyload/plugins/hoster/FileserveCom.py create mode 100644 pyload/plugins/hoster/FileshareInUa.py create mode 100644 pyload/plugins/hoster/FlyFilesNet.py create mode 100644 pyload/plugins/hoster/FourSharedCom.py create mode 100644 pyload/plugins/hoster/FreakshareCom.py create mode 100644 pyload/plugins/hoster/FreevideoCz.py create mode 100644 pyload/plugins/hoster/FshareVn.py create mode 100644 pyload/plugins/hoster/Ftp.py create mode 100644 pyload/plugins/hoster/GamefrontCom.py create mode 100644 pyload/plugins/hoster/GigapetaCom.py create mode 100644 pyload/plugins/hoster/HellshareCz.py create mode 100644 pyload/plugins/hoster/HellspyCz.py create mode 100644 pyload/plugins/hoster/HotfileCom.py create mode 100644 pyload/plugins/hoster/IFileWs.py create mode 100644 pyload/plugins/hoster/IcyFilesCom.py create mode 100644 pyload/plugins/hoster/IfileIt.py create mode 100644 pyload/plugins/hoster/IfolderRu.py create mode 100644 pyload/plugins/hoster/JumbofilesCom.py create mode 100644 pyload/plugins/hoster/LetitbitNet.py create mode 100644 pyload/plugins/hoster/LoadTo.py create mode 100644 pyload/plugins/hoster/LuckyShareNet.py create mode 100644 pyload/plugins/hoster/MediafireCom.py create mode 100644 pyload/plugins/hoster/MegaNz.py create mode 100644 pyload/plugins/hoster/MegasharesCom.py create mode 100644 pyload/plugins/hoster/MovReelCom.py create mode 100644 pyload/plugins/hoster/MultiDebridCom.py create mode 100644 pyload/plugins/hoster/MultishareCz.py create mode 100644 pyload/plugins/hoster/MyvideoDe.py create mode 100644 pyload/plugins/hoster/NarodRu.py create mode 100644 pyload/plugins/hoster/NetloadIn.py create mode 100644 pyload/plugins/hoster/NovafileCom.py create mode 100644 pyload/plugins/hoster/NowDownloadEu.py create mode 100644 pyload/plugins/hoster/OneFichierCom.py create mode 100644 pyload/plugins/hoster/PornhostCom.py create mode 100644 pyload/plugins/hoster/PornhubCom.py create mode 100644 pyload/plugins/hoster/Premium4Me.py create mode 100644 pyload/plugins/hoster/PremiumizeMe.py create mode 100644 pyload/plugins/hoster/PutlockerCom.py create mode 100644 pyload/plugins/hoster/QuickshareCz.py create mode 100644 pyload/plugins/hoster/RapidgatorNet.py create mode 100644 pyload/plugins/hoster/RapidshareCom.py create mode 100644 pyload/plugins/hoster/RarefileNet.py create mode 100644 pyload/plugins/hoster/RealdebridCom.py create mode 100644 pyload/plugins/hoster/RedtubeCom.py create mode 100644 pyload/plugins/hoster/RehostTo.py create mode 100644 pyload/plugins/hoster/ReloadCc.py create mode 100644 pyload/plugins/hoster/RyushareCom.py create mode 100644 pyload/plugins/hoster/SecureUploadEu.py create mode 100644 pyload/plugins/hoster/SendmywayCom.py create mode 100644 pyload/plugins/hoster/SendspaceCom.py create mode 100644 pyload/plugins/hoster/Share4webCom.py create mode 100644 pyload/plugins/hoster/Share76Com.py create mode 100644 pyload/plugins/hoster/ShareFilesCo.py create mode 100644 pyload/plugins/hoster/ShareRapidCom.py create mode 100644 pyload/plugins/hoster/SharebeesCom.py create mode 100644 pyload/plugins/hoster/ShareonlineBiz.py create mode 100644 pyload/plugins/hoster/ShareplaceCom.py create mode 100644 pyload/plugins/hoster/ShragleCom.py create mode 100644 pyload/plugins/hoster/SpeedLoadOrg.py create mode 100644 pyload/plugins/hoster/SpeedfileCz.py create mode 100644 pyload/plugins/hoster/StreamCz.py create mode 100644 pyload/plugins/hoster/TurbobitNet.py create mode 100644 pyload/plugins/hoster/TurbouploadCom.py create mode 100644 pyload/plugins/hoster/TusfilesNet.py create mode 100644 pyload/plugins/hoster/TwoSharedCom.py create mode 100644 pyload/plugins/hoster/UlozTo.py create mode 100644 pyload/plugins/hoster/UloziskoSk.py create mode 100644 pyload/plugins/hoster/UnibytesCom.py create mode 100644 pyload/plugins/hoster/UploadStationCom.py create mode 100644 pyload/plugins/hoster/UploadedTo.py create mode 100644 pyload/plugins/hoster/UploadheroCom.py create mode 100644 pyload/plugins/hoster/UploadingCom.py create mode 100644 pyload/plugins/hoster/UptoboxCom.py create mode 100644 pyload/plugins/hoster/VeehdCom.py create mode 100644 pyload/plugins/hoster/WarserverCz.py create mode 100644 pyload/plugins/hoster/WebshareCz.py create mode 100644 pyload/plugins/hoster/WrzucTo.py create mode 100644 pyload/plugins/hoster/WuploadCom.py create mode 100644 pyload/plugins/hoster/X7To.py create mode 100644 pyload/plugins/hoster/XFileSharingPro.py create mode 100644 pyload/plugins/hoster/XHamsterCom.py create mode 100644 pyload/plugins/hoster/XVideosCom.py create mode 100644 pyload/plugins/hoster/Xdcc.py create mode 100644 pyload/plugins/hoster/XvidstageCom.py create mode 100644 pyload/plugins/hoster/YibaishiwuCom.py create mode 100644 pyload/plugins/hoster/YoupornCom.py create mode 100644 pyload/plugins/hoster/YourfilesTo.py create mode 100644 pyload/plugins/hoster/YoutubeCom.py create mode 100644 pyload/plugins/hoster/ZDF.py create mode 100644 pyload/plugins/hoster/ZeveraCom.py create mode 100644 pyload/plugins/hoster/ZippyshareCom.py create mode 100644 pyload/plugins/hoster/__init__.py create mode 100644 pyload/plugins/internal/AbstractExtractor.py create mode 100644 pyload/plugins/internal/CaptchaService.py create mode 100644 pyload/plugins/internal/DeadHoster.py create mode 100644 pyload/plugins/internal/NetloadInOCR.py create mode 100644 pyload/plugins/internal/OCR.py create mode 100644 pyload/plugins/internal/ShareonlineBizOCR.py create mode 100644 pyload/plugins/internal/SimpleCrypter.py create mode 100644 pyload/plugins/internal/SimpleHoster.py create mode 100644 pyload/plugins/internal/UnRar.py create mode 100644 pyload/plugins/internal/UnZip.py create mode 100644 pyload/plugins/internal/XFSPAccount.py create mode 100644 pyload/plugins/internal/__init__.py (limited to 'pyload/plugins') diff --git a/pyload/plugins/Account.py b/pyload/plugins/Account.py new file mode 100644 index 000000000..2a85e2b44 --- /dev/null +++ b/pyload/plugins/Account.py @@ -0,0 +1,295 @@ +# -*- coding: utf-8 -*- + +from time import time +from traceback import print_exc +from threading import RLock + +from pyload.utils import compare_time, format_size, parseFileSize, lock, from_string +from pyload.Api import AccountInfo +from pyload.network.CookieJar import CookieJar + +from Base import Base + + +class WrongPassword(Exception): + pass + +#noinspection PyUnresolvedReferences +class Account(Base): + """ + Base class for every account plugin. + Just overwrite `login` and cookies will be stored and the account becomes accessible in\ + associated hoster plugin. Plugin should also provide `loadAccountInfo`. \ + An instance of this class is created for every entered account, it holds all \ + fields of AccountInfo ttype, and can be set easily at runtime. + """ + + # constants for special values + UNKNOWN = -1 + UNLIMITED = -2 + + # Default values + owner = None + valid = True + validuntil = -1 + trafficleft = -1 + maxtraffic = -1 + premium = True + activated = True + shared = False + + #: after that time [in minutes] pyload will relogin the account + login_timeout = 600 + #: account data will be reloaded after this time + info_threshold = 600 + + # known options + known_opt = ("time", "limitDL") + + def __init__(self, manager, loginname, password, options): + Base.__init__(self, manager.core) + + if "activated" in options: + self.activated = from_string(options["activated"], "bool") + else: + self.activated = Account.activated + + for opt in self.known_opt: + if opt not in options: + options[opt] = "" + + for opt in options.keys(): + if opt not in self.known_opt: + del options[opt] + + self.loginname = loginname + self.options = options + + self.manager = manager + + self.lock = RLock() + self.timestamp = 0 + self.login_ts = 0 # timestamp for login + self.cj = CookieJar(self.__name__) + self.password = password + self.error = None + + self.init() + + def toInfoData(self): + return AccountInfo(self.__name__, self.loginname, self.owner, self.valid, self.validuntil, self.trafficleft, + self.maxtraffic, + self.premium, self.activated, self.shared, self.options) + + def init(self): + pass + + def login(self, req): + """login into account, the cookies will be saved so the user can be recognized + + :param req: `Request` instance + """ + raise NotImplemented + + def relogin(self): + """ Force a login. """ + req = self.getAccountRequest() + try: + return self._login(req) + finally: + req.close() + + @lock + def _login(self, req): + # set timestamp for login + self.login_ts = time() + + try: + try: + self.login(req) + except TypeError: #TODO: temporary + self.logDebug("Deprecated .login(...) signature omit user, data") + self.login(self.loginname, {"password": self.password}, req) + + self.valid = True + except WrongPassword: + self.logWarning( + _("Could not login with account %(user)s | %(msg)s") % {"user": self.loginname + , "msg": _("Wrong Password")}) + self.valid = False + + except Exception, e: + self.logWarning( + _("Could not login with account %(user)s | %(msg)s") % {"user": self.loginname + , "msg": e}) + self.valid = False + if self.core.debug: + print_exc() + + return self.valid + + def restoreDefaults(self): + self.validuntil = Account.validuntil + self.trafficleft = Account.trafficleft + self.maxtraffic = Account.maxtraffic + self.premium = Account.premium + + def update(self, password=None, options=None): + """ updates the account and returns true if anything changed """ + + self.login_ts = 0 + self.valid = True #set valid, so the login will be retried + + if "activated" in options: + self.activated = from_string(options["avtivated"], "bool") + + if password: + self.password = password + self.relogin() + return True + if options: + # remove unknown options + for opt in options.keys(): + if opt not in self.known_opt: + del options[opt] + + before = self.options + self.options.update(options) + return self.options != before + + def getAccountRequest(self): + return self.core.requestFactory.getRequest(self.__name__, self.cj) + + def getDownloadSettings(self): + """ Can be overwritten to change download settings. Default is no chunkLimit, max dl limit, resumeDownload + + :return: (chunkLimit, limitDL, resumeDownload) / (int, int ,bool) + """ + return -1, 0, True + + @lock + def getAccountInfo(self, force=False): + """retrieve account info's for an user, do **not** overwrite this method!\\ + just use it to retrieve info's in hoster plugins. see `loadAccountInfo` + + :param name: username + :param force: reloads cached account information + :return: dictionary with information + """ + if force or self.timestamp + self.info_threshold * 60 < time(): + + # make sure to login + req = self.getAccountRequest() + self.checkLogin(req) + self.logInfo(_("Get Account Info for %s") % self.loginname) + try: + try: + infos = self.loadAccountInfo(req) + except TypeError: #TODO: temporary + self.logDebug("Deprecated .loadAccountInfo(...) signature, omit user argument.") + infos = self.loadAccountInfo(self.loginname, req) + except Exception, e: + infos = {"error": str(e)} + self.logError(_("Error: %s") % e) + finally: + req.close() + + self.logDebug("Account Info: %s" % str(infos)) + self.timestamp = time() + + self.restoreDefaults() # reset to initial state + if type(infos) == dict: # copy result from dict to class + for k, v in infos.iteritems(): + if hasattr(self, k): + setattr(self, k, v) + else: + self.logDebug("Unknown attribute %s=%s" % (k, v)) + + #TODO: remove user + def loadAccountInfo(self, req): + """ Overwrite this method and set account attributes within this method. + + :param user: Deprecated + :param req: Request instance + :return: + """ + pass + + def getAccountCookies(self, user): + self.logDebug("Deprecated method .getAccountCookies -> use account.cj") + return self.cj + + def getAccountData(self, user): + self.logDebug("Deprecated method .getAccountData -> use fields directly") + return {"password": self.password} + + def isPremium(self, user=None): + if user: self.logDebug("Deprecated Argument user for .isPremium()", user) + return self.premium + + def isUsable(self): + """Check several constraints to determine if account should be used""" + if not self.valid or not self.activated: return False + + if self.options["time"]: + time_data = "" + try: + time_data = self.options["time"] + start, end = time_data.split("-") + if not compare_time(start.split(":"), end.split(":")): + return False + except: + self.logWarning(_("Your Time %s has a wrong format, use: 1:22-3:44") % time_data) + + if 0 <= self.validuntil < time(): + return False + if self.trafficleft is 0: # test explicitly for 0 + return False + + return True + + def parseTraffic(self, string): #returns kbyte + return parseFileSize(string) / 1024 + + def formatTrafficleft(self): + if self.trafficleft is None: + self.getAccountInfo(force=True) + return format_size(self.trafficleft * 1024) + + def wrongPassword(self): + raise WrongPassword + + def empty(self, user=None): + if user: self.logDebug("Deprecated argument user for .empty()", user) + + self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % self.login) + + self.trafficleft = 0 + self.scheduleRefresh(30 * 60) + + def expired(self, user=None): + if user: self.logDebug("Deprecated argument user for .expired()", user) + + self.logWarning(_("Account %s is expired, checking again in 1h") % user) + + self.validuntil = time() - 1 + self.scheduleRefresh(60 * 60) + + def scheduleRefresh(self, time=0, force=True): + """ add a task for refreshing the account info to the scheduler """ + self.logDebug("Scheduled Account refresh for %s in %s seconds." % (self.loginname, time)) + self.core.scheduler.addJob(time, self.getAccountInfo, [force]) + + @lock + def checkLogin(self, req): + """ checks if the user is still logged in """ + if self.login_ts + self.login_timeout * 60 < time(): + if self.login_ts: # separate from fresh login to have better debug logs + self.logDebug("Reached login timeout for %s" % self.loginname) + else: + self.logInfo(_("Login with %s") % self.loginname) + + self._login(req) + return False + + return True diff --git a/pyload/plugins/Addon.py b/pyload/plugins/Addon.py new file mode 100644 index 000000000..ff9c57bef --- /dev/null +++ b/pyload/plugins/Addon.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: RaNaN +""" + +from traceback import print_exc + +#from functools import wraps +from module.utils import has_method, to_list + +from Base import Base + +def class_name(p): + return p.rpartition(".")[2] + + +def AddEventListener(event): + """ Used to register method for events. Arguments needs to match parameter of event + + :param event: Name of event or list of them. + """ + class _klass(object): + def __new__(cls, f, *args, **kwargs): + for ev in to_list(event): + addonManager.addEventListener(class_name(f.__module__), f.func_name, ev) + return f + return _klass + +class ConfigHandler(object): + """ Register method as config handler. + + Your method signature has to be: + def foo(value=None): + + value will be passed to use your method to set the config. + When value is None your method needs to return an interaction task for configuration. + """ + + def __new__(cls, f, *args, **kwargs): + addonManager.addConfigHandler(class_name(f.__module__), f.func_name) + return f + +def AddonHandler(desc, media=None): + """ Register Handler for files, packages, or arbitrary callable methods. + To let the method work on packages/files, media must be set and the argument named pid or fid. + + :param desc: verbose description + :param media: if True or bits of media type + """ + pass + +def AddonInfo(desc): + """ Called to retrieve information about the current state. + Decorated method must return anything convertable into string. + + :param desc: verbose description + """ + pass + +def threaded(f): + """ Decorator to run method in a thread. """ + + #@wraps(f) + def run(*args,**kwargs): + addonManager.startThread(f, *args, **kwargs) + return run + +class Addon(Base): + """ + Base class for addon plugins. Use @threaded decorator for all longer running tasks. + + Decorate methods with @Expose, @AddEventListener, @ConfigHandler + + """ + + #: automatically register event listeners for functions, attribute will be deleted don't use it yourself + event_map = None + + # Alternative to event_map + #: List of events the plugin can handle, name the functions exactly like eventname. + event_list = None # dont make duplicate entries in event_map + + #: periodic call interval in seconds + interval = 60 + + def __init__(self, core, manager, user=None): + Base.__init__(self, core, user) + + #: Provide information in dict here, usable by API `getInfo` + self.info = None + + #: Callback of periodical job task, used by addonmanager + self.cb = None + + #: `AddonManager` + self.manager = manager + + #register events + if self.event_map: + for event, funcs in self.event_map.iteritems(): + if type(funcs) in (list, tuple): + for f in funcs: + self.evm.addEvent(event, getattr(self,f)) + else: + self.evm.addEvent(event, getattr(self,funcs)) + + #delete for various reasons + self.event_map = None + + if self.event_list: + for f in self.event_list: + self.evm.addEvent(f, getattr(self,f)) + + self.event_list = None + + self.initPeriodical() + self.init() + self.setup() + + def initPeriodical(self): + if self.interval >=1: + self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False) + + def _periodical(self): + try: + if self.isActivated(): self.periodical() + except Exception, e: + self.core.log.error(_("Error executing addons: %s") % str(e)) + if self.core.debug: + print_exc() + + self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False) + + def __repr__(self): + return "" % self.__name__ + + def isActivated(self): + """ checks if addon is activated""" + return True if self.__internal__ else self.getConfig("activated") + + def getCategory(self): + return self.core.pluginManager.getCategory(self.__name__) + + def init(self): + pass + + def setup(self): + """ more init stuff if needed """ + pass + + def activate(self): + """ Used to activate the addon """ + if has_method(self.__class__, "coreReady"): + self.logDebug("Deprecated method .coreReady() use activate() instead") + self.coreReady() + + def deactivate(self): + """ Used to deactivate the addon. """ + pass + + def periodical(self): + pass + + def newInteractionTask(self, task): + """ new interaction task for the plugin, it MUST set the handler and timeout or will be ignored """ + pass + + def taskCorrect(self, task): + pass + + def taskInvalid(self, task): + pass + + # public events starts from here + def downloadPreparing(self, pyfile): + pass + + def downloadFinished(self, pyfile): + pass + + def downloadFailed(self, pyfile): + pass + + def packageFinished(self, pypack): + pass + + def beforeReconnecting(self, ip): + pass + + def afterReconnecting(self, ip): + pass \ No newline at end of file diff --git a/pyload/plugins/Base.py b/pyload/plugins/Base.py new file mode 100644 index 000000000..47369e21f --- /dev/null +++ b/pyload/plugins/Base.py @@ -0,0 +1,343 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: RaNaN +""" + +import sys +from time import time, sleep +from random import randint + +from pyload.utils import decode +from pyload.utils.fs import exists, makedirs, join, remove + +# TODO +# more attributes if needed +# get rid of catpcha & container plugins ?! (move to crypter & internals) +# adapt old plugins as needed + +class Fail(Exception): + """ raised when failed """ + +class Retry(Exception): + """ raised when start again from beginning """ + +class Abort(Exception): + """ raised when aborted """ + +class Base(object): + """ + The Base plugin class with all shared methods and every possible attribute for plugin definition. + """ + __version__ = "0.1" + #: Regexp pattern which will be matched for download/crypter plugins + __pattern__ = r"" + #: Internal addon plugin which is always loaded + __internal__ = False + #: When True this addon can be enabled by every user + __user_context__ = False + #: Config definition: list of (name, type, label, default_value) or + #: (name, type, label, short_description, default_value) + __config__ = list() + #: Short description, one liner + __label__ = "" + #: More detailed text + __description__ = """""" + #: List of needed modules + __dependencies__ = tuple() + #: Used to assign a category for addon plugins + __category__ = "" + #: Tags to categorize the plugin, see documentation for further info + __tags__ = tuple() + #: Base64 encoded .png icon, should be 32x32, please don't use sizes above ~2KB, for bigger icons use url. + __icon__ = "" + #: Alternative, link to png icon + __icon_url__ = "" + #: Url with general information/support/discussion + __url__ = "" + #: Url to term of content, user is accepting these when using the plugin + __toc_url__ = "" + #: Url to service (to buy premium) for accounts + __ref_url__ = "" + + __author_name__ = tuple() + __author_mail__ = tuple() + + + def __init__(self, core, user=None): + self.__name__ = self.__class__.__name__ + + #: Core instance + self.core = core + #: logging instance + self.log = core.log + #: core config + self.config = core.config + #: :class:`EventManager` + self.evm = core.eventManager + #: :class:`InteractionManager` + self.im = core.interactionManager + if user: + #: :class:`Api`, user api when user is set + self.api = self.core.api.withUserContext(user) + if self.api: + #: :class:`User`, user related to this plugin + self.user = self.api.user + else: + self.api = self.core.api + self.user = None + else: + self.api = self.core.api + self.user = None + + #: last interaction task + self.task = None + + def logInfo(self, *args, **kwargs): + """ Print args to log at specific level + + :param args: Arbitrary object which should be logged + :param kwargs: sep=(how to separate arguments), default = " | " + """ + self._log("info", *args, **kwargs) + + def logWarning(self, *args, **kwargs): + self._log("warning", *args, **kwargs) + + def logError(self, *args, **kwargs): + self._log("error", *args, **kwargs) + + def logDebug(self, *args, **kwargs): + self._log("debug", *args, **kwargs) + + def _log(self, level, *args, **kwargs): + if "sep" in kwargs: + sep = "%s" % kwargs["sep"] + else: + sep = " | " + + strings = [] + for obj in args: + if type(obj) == unicode: + strings.append(obj) + elif type(obj) == str: + strings.append(decode(obj)) + else: + strings.append(str(obj)) + + getattr(self.log, level)("%s: %s" % (self.__name__, sep.join(strings))) + + def getName(self): + """ Name of the plugin class """ + return self.__name__ + + def setConfig(self, option, value): + """ Set config value for current plugin """ + self.core.config.set(self.__name__, option, value) + + def getConf(self, option): + """ see `getConfig` """ + return self.getConfig(option) + + def getConfig(self, option): + """ Returns config value for current plugin """ + return self.core.config.get(self.__name__, option) + + def setStorage(self, key, value): + """ Saves a value persistently to the database """ + self.core.db.setStorage(self.__name__, key, value) + + def store(self, key, value): + """ same as `setStorage` """ + self.core.db.setStorage(self.__name__, key, value) + + def getStorage(self, key=None, default=None): + """ Retrieves saved value or dict of all saved entries if key is None """ + if key is not None: + return self.core.db.getStorage(self.__name__, key) or default + return self.core.db.getStorage(self.__name__, key) + + def retrieve(self, *args, **kwargs): + """ same as `getStorage` """ + return self.getStorage(*args, **kwargs) + + def delStorage(self, key): + """ Delete entry in db """ + self.core.db.delStorage(self.__name__, key) + + def shell(self): + """ open ipython shell """ + if self.core.debug: + from IPython import embed + #noinspection PyUnresolvedReferences + sys.stdout = sys._stdout + embed() + + def abort(self): + """ Check if plugin is in an abort state, is overwritten by subtypes""" + return False + + def checkAbort(self): + """ Will be overwritten to determine if control flow should be aborted """ + if self.abort(): raise Abort() + + def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False): + """Load content at url and returns it + + :param url: url as string + :param get: GET as dict + :param post: POST as dict, list or string + :param ref: Set HTTP_REFERER header + :param cookies: use saved cookies + :param just_header: if True only the header will be retrieved and returned as dict + :param decode: Whether to decode the output according to http header, should be True in most cases + :return: Loaded content + """ + if not hasattr(self, "req"): raise Exception("Plugin type does not have Request attribute.") + self.checkAbort() + + res = self.req.load(url, get, post, ref, cookies, just_header, decode=decode) + + if self.core.debug: + from inspect import currentframe + + frame = currentframe() + if not exists(join("tmp", self.__name__)): + makedirs(join("tmp", self.__name__)) + + f = open( + join("tmp", self.__name__, "%s_line%s.dump.html" % (frame.f_back.f_code.co_name, frame.f_back.f_lineno)) + , "wb") + del frame # delete the frame or it wont be cleaned + + try: + tmp = res.encode("utf8") + except: + tmp = res + + f.write(tmp) + f.close() + + if just_header: + #parse header + header = {"code": self.req.code} + for line in res.splitlines(): + line = line.strip() + if not line or ":" not in line: continue + + key, none, value = line.partition(":") + key = key.lower().strip() + value = value.strip() + + if key in header: + if type(header[key]) == list: + header[key].append(value) + else: + header[key] = [header[key], value] + else: + header[key] = value + res = header + + return res + + def invalidTask(self): + if self.task: + self.task.invalid() + + def invalidCaptcha(self): + self.logDebug("Deprecated method .invalidCaptcha, use .invalidTask") + self.invalidTask() + + def correctTask(self): + if self.task: + self.task.correct() + + def correctCaptcha(self): + self.logDebug("Deprecated method .correctCaptcha, use .correctTask") + self.correctTask() + + def decryptCaptcha(self, url, get={}, post={}, cookies=False, forceUser=False, imgtype='jpg', + result_type='textual'): + """ Loads a captcha and decrypts it with ocr, plugin, user input + + :param url: url of captcha image + :param get: get part for request + :param post: post part for request + :param cookies: True if cookies should be enabled + :param forceUser: if True, ocr is not used + :param imgtype: Type of the Image + :param result_type: 'textual' if text is written on the captcha\ + or 'positional' for captcha where the user have to click\ + on a specific region on the captcha + + :return: result of decrypting + """ + + img = self.load(url, get=get, post=post, cookies=cookies) + + id = ("%.2f" % time())[-6:].replace(".", "") + temp_file = open(join("tmp", "tmpCaptcha_%s_%s.%s" % (self.__name__, id, imgtype)), "wb") + temp_file.write(img) + temp_file.close() + + name = "%sOCR" % self.__name__ + has_plugin = name in self.core.pluginManager.getPlugins("internal") + + if self.core.captcha: + OCR = self.core.pluginManager.loadClass("internal", name) + else: + OCR = None + + if OCR and not forceUser: + sleep(randint(3000, 5000) / 1000.0) + self.checkAbort() + + ocr = OCR() + result = ocr.get_captcha(temp_file.name) + else: + task = self.im.createCaptchaTask(img, imgtype, temp_file.name, self.__name__, result_type) + self.task = task + + while task.isWaiting(): + if self.abort(): + self.im.removeTask(task) + raise Abort() + sleep(1) + + #TODO task handling + self.im.removeTask(task) + + if task.error and has_plugin: #ignore default error message since the user could use OCR + self.fail(_("Pil and tesseract not installed and no Client connected for captcha decrypting")) + elif task.error: + self.fail(task.error) + elif not task.result: + self.fail(_("No captcha result obtained in appropriate time.")) + + result = task.result + self.log.debug("Received captcha result: %s" % str(result)) + + if not self.core.debug: + try: + remove(temp_file.name) + except: + pass + + return result + + def fail(self, reason): + """ fail and give reason """ + raise Fail(reason) \ No newline at end of file diff --git a/pyload/plugins/Crypter.py b/pyload/plugins/Crypter.py new file mode 100644 index 000000000..b881510ea --- /dev/null +++ b/pyload/plugins/Crypter.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- + +from traceback import print_exc + +from pyload.utils import to_list, has_method, uniqify +from pyload.utils.fs import exists, remove, fs_encode +from pyload.utils.packagetools import parseNames + +from Base import Base, Retry + +class Package: + """ Container that indicates that a new package should be created """ + def __init__(self, name, urls=None, folder=None): + self.name = name + self.urls = urls if urls else [] + self.folder = folder + + # nested packages + self.packs = [] + + def addURL(self, url): + self.urls.append(url) + + def addPackage(self, pack): + self.packs.append(pack) + + def getAllURLs(self): + urls = self.urls + for p in self.packs: + urls.extend(p.getAllURLs()) + return urls + + # same name and urls is enough to be equal for packages + def __eq__(self, other): + return self.name == other.name and self.urls == other.urls + + def __repr__(self): + return u". + + @author: RaNaN, spoob, mkaay +""" + +import os +from time import time + +if os.name != "nt": + from pyload.utils.fs import chown + from pwd import getpwnam + from grp import getgrnam + +from Base import Base, Fail, Retry +from pyload.utils import chunks as _chunks +from pyload.utils.fs import save_join, save_filename, fs_encode, fs_decode,\ + remove, makedirs, chmod, stat, exists, join + +# Import for Hoster Plugins +chunks = _chunks + +class Reconnect(Exception): + """ raised when reconnected """ + +class SkipDownload(Exception): + """ raised when download should be skipped """ + +class Hoster(Base): + """ + Base plugin for hoster plugin. Overwrite getInfo for online status retrieval, process for downloading. + """ + + @staticmethod + def getInfo(urls): + """This method is used to retrieve the online status of files for hoster plugins. + It has to *yield* list of tuples with the result in this format (name, size, status, url), + where status is one of API pyfile statuses. + + :param urls: List of urls + :return: yield list of tuple with results (name, size, status, url) + """ + pass + + def __init__(self, pyfile): + Base.__init__(self, pyfile.m.core) + + self.wantReconnect = False + #: enables simultaneous processing of multiple downloads + self.limitDL = 0 + #: chunk limit + self.chunkLimit = 1 + #: enables resume (will be ignored if server dont accept chunks) + self.resumeDownload = False + + #: plugin is waiting + self.waiting = False + + self.ocr = None #captcha reader instance + #: account handler instance, see :py:class:`Account` + self.account = self.core.accountManager.getAccountForPlugin(self.__name__) + + #: premium status + self.premium = False + #: username/login + self.user = None + + if self.account and not self.account.isUsable(): self.account = None + if self.account: + self.user = self.account.loginname + #: Browser instance, see `network.Browser` + self.req = self.account.getAccountRequest() + # Default: -1, True, True + self.chunkLimit, self.limitDL, self.resumeDownload = self.account.getDownloadSettings() + self.premium = self.account.isPremium() + else: + self.req = self.core.requestFactory.getRequest(self.__name__) + + #: associated pyfile instance, see `PyFile` + self.pyfile = pyfile + self.thread = None # holds thread in future + + #: location where the last call to download was saved + self.lastDownload = "" + #: re match of the last call to `checkDownload` + self.lastCheck = None + #: js engine, see `JsEngine` + self.js = self.core.js + + self.retries = 0 # amount of retries already made + self.html = None # some plugins store html code here + + self.init() + + def getMultiDL(self): + return self.limitDL <= 0 + + def setMultiDL(self, val): + self.limitDL = 0 if val else 1 + + #: virtual attribute using self.limitDL on behind + multiDL = property(getMultiDL, setMultiDL) + + def getChunkCount(self): + if self.chunkLimit <= 0: + return self.config["download"]["chunks"] + return min(self.config["download"]["chunks"], self.chunkLimit) + + def getDownloadLimit(self): + if self.account: + limit = self.account.options.get("limitDL", 0) + if limit == "": limit = 0 + if self.limitDL > 0: # a limit is already set, we use the minimum + return min(int(limit), self.limitDL) + else: + return int(limit) + else: + return self.limitDL + + + def __call__(self): + return self.__name__ + + def init(self): + """initialize the plugin (in addition to `__init__`)""" + pass + + def setup(self): + """ setup for environment and other things, called before downloading (possibly more than one time)""" + pass + + def preprocessing(self, thread): + """ handles important things to do before starting """ + self.thread = thread + + if self.account: + # will force a re-login or reload of account info if necessary + self.account.getAccountInfo() + else: + self.req.clearCookies() + + self.setup() + + self.pyfile.setStatus("starting") + + return self.process(self.pyfile) + + def process(self, pyfile): + """the 'main' method of every plugin, you **have to** overwrite it""" + raise NotImplementedError + + def abort(self): + return self.pyfile.abort + + def resetAccount(self): + """ don't use account and retry download """ + self.account = None + self.req = self.core.requestFactory.getRequest(self.__name__) + self.retry() + + def checksum(self, local_file=None): + """ + return codes: + 0 - checksum ok + 1 - checksum wrong + 5 - can't get checksum + 10 - not implemented + 20 - unknown error + """ + #@TODO checksum check addon + + return True, 10 + + + def setWait(self, seconds, reconnect=False): + """Set a specific wait time later used with `wait` + + :param seconds: wait time in seconds + :param reconnect: True if a reconnect would avoid wait time + """ + if reconnect: + self.wantReconnect = True + self.pyfile.waitUntil = time() + int(seconds) + + def wait(self): + """ waits the time previously set """ + self.waiting = True + self.pyfile.setStatus("waiting") + + while self.pyfile.waitUntil > time(): + self.thread.m.reconnecting.wait(2) + + self.checkAbort() + if self.thread.m.reconnecting.isSet(): + self.waiting = False + self.wantReconnect = False + raise Reconnect + + self.waiting = False + self.pyfile.setStatus("starting") + + def offline(self): + """ fail and indicate file is offline """ + raise Fail("offline") + + def tempOffline(self): + """ fail and indicates file ist temporary offline, the core may take consequences """ + raise Fail("temp. offline") + + def retry(self, max_tries=3, wait_time=1, reason=""): + """Retries and begin again from the beginning + + :param max_tries: number of maximum retries + :param wait_time: time to wait in seconds + :param reason: reason for retrying, will be passed to fail if max_tries reached + """ + if 0 < max_tries <= self.retries: + if not reason: reason = "Max retries reached" + raise Fail(reason) + + self.wantReconnect = False + self.setWait(wait_time) + self.wait() + + self.retries += 1 + raise Retry(reason) + + + def download(self, url, get={}, post={}, ref=True, cookies=True, disposition=False): + """Downloads the content at url to download folder + + :param url: + :param get: + :param post: + :param ref: + :param cookies: + :param disposition: if True and server provides content-disposition header\ + the filename will be changed if needed + :return: The location where the file was saved + """ + self.checkForSameFiles() + self.checkAbort() + + self.pyfile.setStatus("downloading") + + download_folder = self.config['general']['download_folder'] + + location = save_join(download_folder, self.pyfile.package().folder) + + if not exists(location): + makedirs(location, int(self.core.config["permission"]["folder"], 8)) + + if self.core.config["permission"]["change_dl"] and os.name != "nt": + try: + uid = getpwnam(self.config["permission"]["user"])[2] + gid = getgrnam(self.config["permission"]["group"])[2] + + chown(location, uid, gid) + except Exception, e: + self.log.warning(_("Setting User and Group failed: %s") % str(e)) + + # convert back to unicode + location = fs_decode(location) + name = save_filename(self.pyfile.name) + + filename = join(location, name) + + self.core.addonManager.dispatchEvent("download:start", self.pyfile, url, filename) + + try: + newname = self.req.httpDownload(url, filename, get=get, post=post, ref=ref, cookies=cookies, + chunks=self.getChunkCount(), resume=self.resumeDownload, + disposition=disposition) + finally: + self.pyfile.size = self.req.size + + if disposition and newname and newname != name: #triple check, just to be sure + self.log.info("%(name)s saved as %(newname)s" % {"name": name, "newname": newname}) + self.pyfile.name = newname + filename = join(location, newname) + + fs_filename = fs_encode(filename) + + if self.core.config["permission"]["change_file"]: + chmod(fs_filename, int(self.core.config["permission"]["file"], 8)) + + if self.core.config["permission"]["change_dl"] and os.name != "nt": + try: + uid = getpwnam(self.config["permission"]["user"])[2] + gid = getgrnam(self.config["permission"]["group"])[2] + + chown(fs_filename, uid, gid) + except Exception, e: + self.log.warning(_("Setting User and Group failed: %s") % str(e)) + + self.lastDownload = filename + return self.lastDownload + + def checkDownload(self, rules, api_size=0, max_size=50000, delete=True, read_size=0): + """ checks the content of the last downloaded file, re match is saved to `lastCheck` + + :param rules: dict with names and rules to match (compiled regexp or strings) + :param api_size: expected file size + :param max_size: if the file is larger then it wont be checked + :param delete: delete if matched + :param read_size: amount of bytes to read from files larger then max_size + :return: dictionary key of the first rule that matched + """ + lastDownload = fs_encode(self.lastDownload) + if not exists(lastDownload): return None + + size = stat(lastDownload) + size = size.st_size + + if api_size and api_size <= size: return None + elif size > max_size and not read_size: return None + self.log.debug("Download Check triggered") + f = open(lastDownload, "rb") + content = f.read(read_size if read_size else -1) + f.close() + #produces encoding errors, better log to other file in the future? + #self.log.debug("Content: %s" % content) + for name, rule in rules.iteritems(): + if type(rule) in (str, unicode): + if rule in content: + if delete: + remove(lastDownload) + return name + elif hasattr(rule, "search"): + m = rule.search(content) + if m: + if delete: + remove(lastDownload) + self.lastCheck = m + return name + + + def getPassword(self): + """ get the password the user provided in the package""" + password = self.pyfile.package().password + if not password: return "" + return password + + + def checkForSameFiles(self, starting=False): + """ checks if same file was/is downloaded within same package + + :param starting: indicates that the current download is going to start + :raises SkipDownload: + """ + + pack = self.pyfile.package() + + for pyfile in self.core.files.cachedFiles(): + if pyfile != self.pyfile and pyfile.name == self.pyfile.name and pyfile.package().folder == pack.folder: + if pyfile.status in (0, 12): #finished or downloading + raise SkipDownload(pyfile.pluginname) + elif pyfile.status in ( + 5, 7) and starting: #a download is waiting/starting and was apparently started before + raise SkipDownload(pyfile.pluginname) + + download_folder = self.config['general']['download_folder'] + location = save_join(download_folder, pack.folder, self.pyfile.name) + + if starting and self.core.config['download']['skip_existing'] and exists(location): + size = os.stat(location).st_size + if size >= self.pyfile.size: + raise SkipDownload("File exists.") + + pyfile = self.core.db.findDuplicates(self.pyfile.id, self.pyfile.package().folder, self.pyfile.name) + if pyfile: + if exists(location): + raise SkipDownload(pyfile[0]) + + self.log.debug("File %s not skipped, because it does not exists." % self.pyfile.name) + + def clean(self): + """ clean everything and remove references """ + if hasattr(self, "pyfile"): + del self.pyfile + if hasattr(self, "req"): + self.req.close() + del self.req + if hasattr(self, "thread"): + del self.thread + if hasattr(self, "html"): + del self.html diff --git a/pyload/plugins/MultiHoster.py b/pyload/plugins/MultiHoster.py new file mode 100644 index 000000000..8825cc2f8 --- /dev/null +++ b/pyload/plugins/MultiHoster.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +from time import time + +from pyload.utils import remove_chars + +from Account import Account + +def normalize(domain): + """ Normalize domain/plugin name, so they are comparable """ + return remove_chars(domain.strip().lower(), "-.") + +#noinspection PyUnresolvedReferences +class MultiHoster(Account): + """ + Base class for MultiHoster services. + This is also an Account instance so you should see :class:`Account` and overwrite necessary methods. + Multihoster becomes only active when an Account was entered and the MultiHoster addon was activated. + You need to overwrite `loadHosterList` and a corresponding :class:`Hoster` plugin with the same name should + be available to make your service working. + """ + + #: List of hoster names that will be replaced so pyLoad will recognize them: (orig_name, pyload_name) + replacements = [("freakshare.net", "freakshare.com")] + + #: Load new hoster list every x seconds + hoster_timeout = 300 + + def __init__(self, *args, **kwargs): + + # Hoster list + self.hoster = [] + # Timestamp + self.ts = 0 + + Account.__init__(self, *args, **kwargs) + + def loadHosterList(self, req): + """Load list of supported hoster + + :return: List of domain names + """ + raise NotImplementedError + + + def isHosterUsuable(self, domain): + """ Determine before downloading if hoster should be used. + + :param domain: domain name + :return: True to let the MultiHoster download, False to fallback to default plugin + """ + return True + + def getHosterList(self, force=False): + if self.ts + self.hoster_timeout < time() or force: + req = self.getAccountRequest() + try: + self.hoster = self.loadHosterList(req) + except Exception, e: + self.logError(e) + return [] + finally: + req.close() + + for rep in self.replacements: + if rep[0] in self.hoster: + self.hoster.remove(rep[0]) + if rep[1] not in self.hoster: + self.hoster.append(rep[1]) + + self.ts = time() + + return self.hoster \ No newline at end of file diff --git a/pyload/plugins/ReCaptcha.py b/pyload/plugins/ReCaptcha.py new file mode 100644 index 000000000..e47522b4a --- /dev/null +++ b/pyload/plugins/ReCaptcha.py @@ -0,0 +1,22 @@ +import re + +class ReCaptcha(): + def __init__(self, plugin): + self.plugin = plugin + self.plugin.logDebug("Deprecated usage of ReCaptcha: Use CaptchaService instead") + + def challenge(self, id): + js = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={"k":id}, cookies=True) + + try: + challenge = re.search("challenge : '(.*?)',", js).group(1) + server = re.search("server : '(.*?)',", js).group(1) + except: + self.plugin.fail("recaptcha error") + result = self.result(server,challenge) + + return challenge, result + + def result(self, server, challenge): + return self.plugin.decryptCaptcha("%simage"%server, get={"c":challenge}, cookies=True, imgtype="jpg") + diff --git a/pyload/plugins/__init__.py b/pyload/plugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyload/plugins/accounts/AlldebridCom.py b/pyload/plugins/accounts/AlldebridCom.py new file mode 100644 index 000000000..baaa9d264 --- /dev/null +++ b/pyload/plugins/accounts/AlldebridCom.py @@ -0,0 +1,49 @@ +from module.plugins.Account import Account +import xml.dom.minidom as dom +from BeautifulSoup import BeautifulSoup +from time import time +import re +import urllib + +class AlldebridCom(Account): + __name__ = "AlldebridCom" + __version__ = "0.21" + __type__ = "account" + __description__ = """AllDebrid.com account plugin""" + __author_name__ = ("Andy, Voigt") + __author_mail__ = ("spamsales@online.de") + + def loadAccountInfo(self, user, req): + data = self.getAccountData(user) + page = req.load("http://www.alldebrid.com/account/") + soup=BeautifulSoup(page) + #Try to parse expiration date directly from the control panel page (better accuracy) + try: + time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string + self.log.debug("Account expires in: %s" % time_text) + p = re.compile('\d+') + exp_data=p.findall(time_text) + exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60 + #Get expiration date from API + except: + data = self.getAccountData(user) + page = req.load("http://www.alldebrid.com/api.php?action=info_user&login=%s&pw=%s" % (user, data["password"])) + self.log.debug(page) + xml = dom.parseString(page) + exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400 + account_info = {"validuntil": exp_time, "trafficleft": -1} + return account_info + + def login(self, user, data, req): + + urlparams = urllib.urlencode({'action':'login','login_login':user,'login_password':data["password"]}) + page = req.load("http://www.alldebrid.com/register/?%s" % (urlparams)) + + if "This login doesn't exist" in page: + self.wrongPassword() + + if "The password is not valid" in page: + self.wrongPassword() + + if "Invalid captcha" in page: + self.wrongPassword() diff --git a/pyload/plugins/accounts/BayfilesCom.py b/pyload/plugins/accounts/BayfilesCom.py new file mode 100644 index 000000000..0d036488b --- /dev/null +++ b/pyload/plugins/accounts/BayfilesCom.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +from module.plugins.Account import Account +from module.common.json_layer import json_loads +import re +from time import time, mktime, strptime + +class BayfilesCom(Account): + __name__ = "BayfilesCom" + __version__ = "0.02" + __type__ = "account" + __description__ = """bayfiles.com account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def loadAccountInfo(self, user, req): + for i in range(2): + response = json_loads(req.load("http://api.bayfiles.com/v1/account/info")) + self.logDebug(response) + if not response["error"]: + break + self.logWarning(response["error"]) + self.relogin() + + return {"premium": bool(response['premium']), \ + "trafficleft": -1, \ + "validuntil": response['expires'] if response['expires'] >= int(time()) else -1} + + def login(self, user, data, req): + response = json_loads(req.load("http://api.bayfiles.com/v1/account/login/%s/%s" % (user, data["password"]))) + self.logDebug(response) + if response["error"]: + self.logError(response["error"]) + self.wrongPassword() \ No newline at end of file diff --git a/pyload/plugins/accounts/BitshareCom.py b/pyload/plugins/accounts/BitshareCom.py new file mode 100644 index 000000000..a4f56e31c --- /dev/null +++ b/pyload/plugins/accounts/BitshareCom.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: pking +""" + +from module.plugins.Account import Account + +class BitshareCom(Account): + __name__ = "BitshareCom" + __version__ = "0.11" + __type__ = "account" + __description__ = """Bitshare account plugin""" + __author_name__ = ("Paul King") + + def loadAccountInfo(self, user, req): + page = req.load("http://bitshare.com/mysettings.html") + + if "\"http://bitshare.com/myupgrade.html\">Free" in page: + return {"validuntil": -1, "trafficleft":-1, "premium": False} + + if not '' in page: + self.core.log.warning(_("Activate direct Download in your Bitshare Account")) + + return {"validuntil": -1, "trafficleft": -1, "premium": True} + + + def login(self, user, data, req): + page = req.load("http://bitshare.com/login.html", post={ "user" : user, "password" : data["password"], "submit" :"Login"}, cookies=True) + if "login" in req.lastEffectiveURL: + self.wrongPassword() diff --git a/pyload/plugins/accounts/BoltsharingCom.py b/pyload/plugins/accounts/BoltsharingCom.py new file mode 100644 index 000000000..678591d1d --- /dev/null +++ b/pyload/plugins/accounts/BoltsharingCom.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +from module.plugins.internal.XFSPAccount import XFSPAccount + +class BoltsharingCom(XFSPAccount): + __name__ = "BoltsharingCom" + __version__ = "0.01" + __type__ = "account" + __description__ = """Boltsharing.com account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + MAIN_PAGE = "http://boltsharing.com/" diff --git a/pyload/plugins/accounts/CramitIn.py b/pyload/plugins/accounts/CramitIn.py new file mode 100644 index 000000000..182c9d647 --- /dev/null +++ b/pyload/plugins/accounts/CramitIn.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +from module.plugins.internal.XFSPAccount import XFSPAccount + +class CramitIn(XFSPAccount): + __name__ = "CramitIn" + __version__ = "0.01" + __type__ = "account" + __description__ = """cramit.in account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + MAIN_PAGE = "http://cramit.in/" \ No newline at end of file diff --git a/pyload/plugins/accounts/CyberlockerCh.py b/pyload/plugins/accounts/CyberlockerCh.py new file mode 100644 index 000000000..31e0c3e24 --- /dev/null +++ b/pyload/plugins/accounts/CyberlockerCh.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from module.plugins.internal.XFSPAccount import XFSPAccount +from module.plugins.internal.SimpleHoster import parseHtmlForm + +class CyberlockerCh(XFSPAccount): + __name__ = "CyberlockerCh" + __version__ = "0.01" + __type__ = "account" + __description__ = """CyberlockerCh account plugin""" + __author_name__ = ("stickell") + __author_mail__ = ("l.stickell@yahoo.it") + + MAIN_PAGE = "http://cyberlocker.ch/" + + def login(self, user, data, req): + html = req.load(self.MAIN_PAGE + 'login.html', decode = True) + + action, inputs = parseHtmlForm('name="FL"', html) + if not inputs: + inputs = {"op": "login", + "redirect": self.MAIN_PAGE} + + inputs.update({"login": user, + "password": data['password']}) + + # Without this a 403 Forbidden is returned + req.http.lastURL = self.MAIN_PAGE + 'login.html' + html = req.load(self.MAIN_PAGE, post = inputs, decode = True) + + if 'Incorrect Login or Password' in html or '>Error<' in html: + self.wrongPassword() diff --git a/pyload/plugins/accounts/CzshareCom.py b/pyload/plugins/accounts/CzshareCom.py new file mode 100644 index 000000000..7b1a8edc5 --- /dev/null +++ b/pyload/plugins/accounts/CzshareCom.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +from time import mktime, strptime +import re + +from module.plugins.Account import Account + + +class CzshareCom(Account): + __name__ = "CzshareCom" + __version__ = "0.13" + __type__ = "account" + __description__ = """czshare.com account plugin""" + __author_name__ = ("zoidberg", "stickell") + __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + + CREDIT_LEFT_PATTERN = r'\s*([0-9 ,]+) (KiB|MiB|GiB)\s*([^<]*)\s*' + + def loadAccountInfo(self, user, req): + html = req.load("http://czshare.com/prehled_kreditu/") + + found = re.search(self.CREDIT_LEFT_PATTERN, html) + if not found: + return {"validuntil": 0, "trafficleft": 0} + else: + credits = float(found.group(1).replace(' ', '').replace(',', '.')) + credits = credits * 1024 ** {'KiB': 0, 'MiB': 1, 'GiB': 2}[found.group(2)] + validuntil = mktime(strptime(found.group(3), '%d.%m.%y %H:%M')) + return {"validuntil": validuntil, "trafficleft": credits} + + def login(self, user, data, req): + + html = req.load('https://czshare.com/index.php', post={ + "Prihlasit": "Prihlasit", + "login-password": data["password"], + "login-name": user + }) + + if '
. # +############################################################################ + +import re +import _strptime +import time + +from module.plugins.Account import Account + + +class DebridItaliaCom(Account): + __name__ = "DebridItaliaCom" + __version__ = "0.1" + __type__ = "account" + __description__ = """debriditalia.com account plugin""" + __author_name__ = ("stickell") + __author_mail__ = ("l.stickell@yahoo.it") + + WALID_UNTIL_PATTERN = r"Premium valid till: (?P[^|]+) \|" + + def loadAccountInfo(self, user, req): + if 'Account premium not activated' in self.html: + return {"premium": False, "validuntil": None, "trafficleft": None} + + m = re.search(self.WALID_UNTIL_PATTERN, self.html) + if m: + validuntil = int(time.mktime(time.strptime(m.group('D'), "%d/%m/%Y %H:%M"))) + return {"premium": True, "validuntil": validuntil, "trafficleft": -1} + else: + self.logError('Unable to retrieve account information - Plugin may be out of date') + + def login(self, user, data, req): + self.html = req.load("http://debriditalia.com/login.php", + get={"u": user, "p": data["password"]}) + if 'NO' in self.html: + self.wrongPassword() diff --git a/pyload/plugins/accounts/DepositfilesCom.py b/pyload/plugins/accounts/DepositfilesCom.py new file mode 100644 index 000000000..b0730de8e --- /dev/null +++ b/pyload/plugins/accounts/DepositfilesCom.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: mkaay +""" + +from module.plugins.Account import Account +import re +from time import strptime, mktime + +class DepositfilesCom(Account): + __name__ = "DepositfilesCom" + __version__ = "0.1" + __type__ = "account" + __description__ = """depositfiles.com account plugin""" + __author_name__ = ("mkaay") + __author_mail__ = ("mkaay@mkaay.de") + + def loadAccountInfo(self, user, req): + + src = req.load("http://depositfiles.com/de/gold/") + validuntil = re.search("noch den Gold-Zugriff: (.*?)
", src).group(1) + + validuntil = int(mktime(strptime(validuntil, "%Y-%m-%d %H:%M:%S"))) + + tmp = {"validuntil":validuntil, "trafficleft":-1} + return tmp + + def login(self, user, data, req): + + req.load("http://depositfiles.com/de/gold/payment.php") + src = req.load("http://depositfiles.com/de/login.php", get={"return": "/de/gold/payment.php"}, post={"login": user, "password": data["password"]}) + if r'
Sie haben eine falsche Benutzername-Passwort-Kombination verwendet.
' in src: + self.wrongPassword() diff --git a/pyload/plugins/accounts/EasybytezCom.py b/pyload/plugins/accounts/EasybytezCom.py new file mode 100644 index 000000000..ba7829b83 --- /dev/null +++ b/pyload/plugins/accounts/EasybytezCom.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +from module.plugins.Account import Account +from module.plugins.internal.SimpleHoster import parseHtmlForm +import re +from module.utils import parseFileSize +from time import mktime, strptime + +class EasybytezCom(Account): + __name__ = "EasybytezCom" + __version__ = "0.02" + __type__ = "account" + __description__ = """EasyBytez.com account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + VALID_UNTIL_PATTERN = r'Premium account expire:([^<]+)' + TRAFFIC_LEFT_PATTERN = r'Traffic available today:(?P[^<]+)' + + def loadAccountInfo(self, user, req): + html = req.load("http://www.easybytez.com/?op=my_account", decode = True) + + validuntil = trafficleft = None + premium = False + + found = re.search(self.VALID_UNTIL_PATTERN, html) + if found: + premium = True + trafficleft = -1 + try: + self.logDebug(found.group(1)) + validuntil = mktime(strptime(found.group(1), "%d %B %Y")) + except Exception, e: + self.logError(e) + else: + found = re.search(self.TRAFFIC_LEFT_PATTERN, html) + if found: + trafficleft = found.group(1) + if "Unlimited" in trafficleft: + premium = True + else: + trafficleft = parseFileSize(trafficleft) / 1024 + + return ({"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium}) + + def login(self, user, data, req): + html = req.load('http://www.easybytez.com/login.html', decode = True) + action, inputs = parseHtmlForm('name="FL"', html) + inputs.update({"login": user, + "password": data['password'], + "redirect": "http://www.easybytez.com/"}) + + html = req.load(action, post = inputs, decode = True) + + if 'Incorrect Login or Password' in html or '>Error<' in html: + self.wrongPassword() \ No newline at end of file diff --git a/pyload/plugins/accounts/EgoFilesCom.py b/pyload/plugins/accounts/EgoFilesCom.py new file mode 100644 index 000000000..da1ed03ad --- /dev/null +++ b/pyload/plugins/accounts/EgoFilesCom.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +from module.plugins.Account import Account +import re +import time +from module.utils import parseFileSize + +class EgoFilesCom(Account): + __name__ = "EgoFilesCom" + __version__ = "0.2" + __type__ = "account" + __description__ = """egofiles.com account plugin""" + __author_name__ = ("stickell") + __author_mail__ = ("l.stickell@yahoo.it") + + PREMIUM_ACCOUNT_PATTERN = '
\s*Premium: (?P

[^/]*) / Traffic left: (?P[\d.]*) (?P\w*)\s*\\n\s*
' + + def loadAccountInfo(self, user, req): + html = req.load("http://egofiles.com") + if 'You are logged as a Free User' in html: + return {"premium": False, "validuntil": None, "trafficleft": None} + + m = re.search(self.PREMIUM_ACCOUNT_PATTERN, html) + if m: + validuntil = int(time.mktime(time.strptime(m.group('P'), "%Y-%m-%d %H:%M:%S"))) + trafficleft = parseFileSize(m.group('T'), m.group('U')) / 1024 + return {"premium": True, "validuntil": validuntil, "trafficleft": trafficleft} + else: + self.logError('Unable to retrieve account information - Plugin may be out of date') + + def login(self, user, data, req): + # Set English language + req.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True) + + html = req.load("http://egofiles.com/ajax/register.php", + post={"log": 1, + "loginV": user, + "passV": data["password"]}) + if 'Login successful' not in html: + self.wrongPassword() diff --git a/pyload/plugins/accounts/EuroshareEu.py b/pyload/plugins/accounts/EuroshareEu.py new file mode 100644 index 000000000..42967d975 --- /dev/null +++ b/pyload/plugins/accounts/EuroshareEu.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +from module.plugins.Account import Account +from time import mktime, strptime +from string import replace +import re + +class EuroshareEu(Account): + __name__ = "EuroshareEu" + __version__ = "0.01" + __type__ = "account" + __description__ = """euroshare.eu account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def loadAccountInfo(self, user, req): + self.relogin(user) + html = req.load("http://euroshare.eu/customer-zone/settings/") + + found = re.search('id="input_expire_date" value="(\d+\.\d+\.\d+ \d+:\d+)"', html) + if found is None: + premium, validuntil = False, -1 + else: + premium = True + validuntil = mktime(strptime(found.group(1), "%d.%m.%Y %H:%M")) + + return {"validuntil": validuntil, "trafficleft": -1, "premium": premium} + + def login(self, user, data, req): + + html = req.load('http://euroshare.eu/customer-zone/login/', post={ + "trvale": "1", + "login": user, + "password": data["password"] + }, decode=True) + + if u">Nesprávne prihlasovacie meno alebo heslo" in html: + self.wrongPassword() \ No newline at end of file diff --git a/pyload/plugins/accounts/FastshareCz.py b/pyload/plugins/accounts/FastshareCz.py new file mode 100644 index 000000000..69bbb0827 --- /dev/null +++ b/pyload/plugins/accounts/FastshareCz.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +import re +from module.plugins.Account import Account +from module.utils import parseFileSize + + +class FastshareCz(Account): + __name__ = "FastshareCz" + __version__ = "0.02" + __type__ = "account" + __description__ = """fastshare.cz account plugin""" + __author_name__ = ("zoidberg", "stickell") + __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + + def loadAccountInfo(self, user, req): + html = req.load("http://www.fastshare.cz/user", decode=True) + + found = re.search(r'(?:Kredit|Credit)\s*: (.+?) ', html) + if found: + trafficleft = parseFileSize(found.group(1)) / 1024 + premium = True if trafficleft else False + else: + trafficleft = None + premium = False + + return {"validuntil": -1, "trafficleft": trafficleft, "premium": premium} + + def login(self, user, data, req): + req.load('http://www.fastshare.cz/login') # Do not remove or it will not login + html = req.load('http://www.fastshare.cz/sql.php', post={ + "heslo": data['password'], + "login": user + }, decode=True) + + if u'>Špatné uživatelské jméno nebo heslo.<' in html: + self.wrongPassword() \ No newline at end of file diff --git a/pyload/plugins/accounts/FilebeerInfo.py b/pyload/plugins/accounts/FilebeerInfo.py new file mode 100644 index 000000000..40ab70519 --- /dev/null +++ b/pyload/plugins/accounts/FilebeerInfo.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: zoidberg +""" + +import re +from time import mktime, strptime +from module.plugins.Account import Account +from module.utils import parseFileSize + +class FilebeerInfo(Account): + __name__ = "FilebeerInfo" + __version__ = "0.02" + __type__ = "account" + __description__ = """filebeer.info account plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + VALID_UNTIL_PATTERN = r'Reverts To Free Account:\s\s*\s*(.*?)\s*' + + def loadAccountInfo(self, user, req): + html = req.load("http://filebeer.info/upgrade.php", decode = True) + premium = not 'Free User ' in html + + validuntil = None + if premium: + try: + validuntil = mktime(strptime(re.search(self.VALID_UNTIL_PATTERN, html).group(1), "%d/%m/%Y %H:%M:%S")) + except Exception, e: + self.logError("Unable to parse account info", e) + + return {"validuntil": validuntil, "trafficleft": -1, "premium": premium} + + def login(self, user, data, req): + html = req.load('http://filebeer.info/login.php', post = { + "submit": 'Login', + "loginPassword": data['password'], + "loginUsername": user, + "submitme": '1' + }, decode = True) + + if "