From 3b4c2f1e72b172c7781cda315f02f27320e13b52 Mon Sep 17 00:00:00 2001 From: Glenn Guy Date: Wed, 19 Sep 2018 21:51:00 +1000 Subject: [PATCH] Initial commit --- .gitignore | 26 +- .travis.yml | 33 ++ LICENSE | 674 +++++++++++++++++++++++++ README.md | 23 + addon.xml | 18 + default.py | 56 ++ icon.png | Bin 0 -> 94229 bytes resources/__init__.py | 1 + resources/language/English/strings.xml | 14 + resources/lib/__init__.py | 1 + resources/lib/categories.py | 25 + resources/lib/classes.py | 76 +++ resources/lib/comm.py | 75 +++ resources/lib/config.py | 119 +++++ resources/lib/menus.py | 59 +++ resources/lib/ooyalahelper.py | 186 +++++++ resources/lib/play.py | 40 ++ resources/lib/storageserverdummy.py | 30 ++ resources/lib/telstra_auth.py | 177 +++++++ resources/settings.xml | 14 + 20 files changed, 1624 insertions(+), 23 deletions(-) create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 addon.xml create mode 100644 default.py create mode 100644 icon.png create mode 100644 resources/__init__.py create mode 100644 resources/language/English/strings.xml create mode 100644 resources/lib/__init__.py create mode 100644 resources/lib/categories.py create mode 100644 resources/lib/classes.py create mode 100644 resources/lib/comm.py create mode 100644 resources/lib/config.py create mode 100644 resources/lib/menus.py create mode 100644 resources/lib/ooyalahelper.py create mode 100644 resources/lib/play.py create mode 100644 resources/lib/storageserverdummy.py create mode 100644 resources/lib/telstra_auth.py create mode 100644 resources/settings.xml diff --git a/.gitignore b/.gitignore index acf4f59..a30df11 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,3 @@ -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= +*.pyc +*.pyo +*.zip diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a7f061f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,33 @@ +language: python +env: + global: + - secure: C0Tqtj3OeCT25kIRhSw57eMMjaNn5vFbTqmpj6pvHlObDLqjliv8nbQXQvIZc5jxFhyiGfj+Ym0YNO3NnOk7yiOvHtpqyj0Q3tkev0GdECU7jszJg3FzYqTQ5PmJF1o++ecO9hDRgK2vtvg4lwFtovEj7BHr9Q+/Wph9KoymSTzT2Ufsg+8wQ3mqfC43FdEuiyZxAjbI/jVugs3jafC/7UmV9WlCMqJLebhB+lRLRTqesDOccO1aOwIO7nmWuqWnMX18se9J93aALMAp5rXH7r6LM5h6T/T6FyaZSacIwO+Mx/xYkB8n+b7rSc3eyGcks4wncuGYxBIjVNtLsmlTpr1E9YacQuzCPq4D2ktzEcBlBLJWpabruhetW1w4+tYI9MK8XTJhq1KWKukBjxJlELFReZWUvasQ4YrKox5mIgmCJ/1yiwLH2DkqX06W+Jqq2OHhNaFXcwwoEvMmoFgUtYyq2TOm1XmmV508sUd35gatmMTiT8eoD9zIusSx8NOCVUE91Zrt4j8kAcHipsHpcp1PbUV1jKPXEIeiYsALVd2rJqR1LJLAF6urdf1MVc40nVklBDYz7TjRNW/jesifVWvSeYYrI/LKUa3h86gay0n6ibsEBdoiDAtYhFh4sFSsF41dFbfMSd/tLG+vcf6L6go6yM5v9wGGYvZNaNXHv34= +install: + - pip install GitPython + - export TRAVIS_COMMIT_MSG="$TRAVIS_REPO_SLUG - $(git log --format=%B --no-merges -n 1)" +script: + - test "$TRAVIS_PULL_REQUEST" = "false" || travis_terminate 0 + - test "$TRAVIS_BRANCH" = "$TRAVIS_TAG" -o "$TRAVIS_BRANCH" = "master" || travis_terminate 0 + - git config --global user.email 'aussieaddons@aussieaddons.com' + - git config --global user.name 'Aussie Add-ons Bot' + - > + git clone https://github.com/xbmc-catchuptv-au/repo-devel.git $TRAVIS_BUILD_DIR/.deploy-devel && + cd $TRAVIS_BUILD_DIR/.deploy-devel && + ./manage_repo.py $TRAVIS_BUILD_DIR || travis_terminate 1 + - git config credential.helper "store --file=.git/credentials" + - echo "https://${GH_TOKEN}:@github.com" > .git/credentials + - > + git add . && + git commit --allow-empty -m "$TRAVIS_COMMIT_MSG" && + git push || travis_terminate 1 + - if [ -z "$TRAVIS_TAG" ]; then travis_terminate 0; fi + - > + git clone https://github.com/xbmc-catchuptv-au/repo.git $TRAVIS_BUILD_DIR/.deploy-prod && + cd $TRAVIS_BUILD_DIR/.deploy-prod && + ./manage_repo.py $TRAVIS_BUILD_DIR || travis_terminate 1 + - git config credential.helper "store --file=.git/credentials" + - echo "https://${GH_TOKEN}:@github.com" > .git/credentials + - > + git add . && + git commit --allow-empty -m "Update $(basename `git -C $TRAVIS_BUILD_DIR rev-parse --show-toplevel`) to $TRAVIS_TAG" && + git push || travis_terminate 1 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bcc95c5 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +#Soccer Live addon for Kodi + +## This add-on supports the free Live Pass offer for eligible Telstra customers. In-app subscriptions through the App Store/Google Play are NOT supported. + +##Requirements + +Kodi v17 is the minimum recommended version. If you are having SSL errors, upgrading Kodi should solve them. On some platforms earlier versions will work fine. + +You will need a Telstra ID account with an eligible service attached to use this add-on. Most Telstra Mobile customers are eligible for a free subscription with their plan. Please see their [website](https://www.telstra.com.au/tv-movies-music/sports-offer) for details. + +##How to install + +Soccer Live is available from the Catch Up TV AU repository located [here](https://github.com/aussieaddons/repo). Head on over and follow the instructions to install the repo, then install the add-on. + +##Settings + +You will need to enter your Telstra ID username and password to view videos. + +The live streaming bitrates reflect an average bitrate only, you should ideally have twice the bandwidth available to ensure buffer free viewing. + +##Issues + +Please let us know of any errors by opening an [issue](https://github.com/aussieaddons/plugin.video.soccer-live/issues) ticket. It would be great if you could attach a Kodi debug log file as well. Follow this [guide](http://kodi.wiki/view/Log_file/Easy). diff --git a/addon.xml b/addon.xml new file mode 100644 index 0000000..4e23bd7 --- /dev/null +++ b/addon.xml @@ -0,0 +1,18 @@ + + + + + + + + + + video + + + Soccer Live add-on + Soccer Live is an unofficial add-on for Australian soccer content + video + all + + \ No newline at end of file diff --git a/default.py b/default.py new file mode 100644 index 0000000..332a0c3 --- /dev/null +++ b/default.py @@ -0,0 +1,56 @@ +import os +import sys +import xbmc +import xbmcgui +import xbmcaddon +from urlparse import parse_qsl + +addon = xbmcaddon.Addon() +cwd = xbmc.translatePath(addon.getAddonInfo('path')).decode("utf-8") +BASE_RESOURCE_PATH = os.path.join(cwd, 'resources', 'lib') +sys.path.append(BASE_RESOURCE_PATH) + +import play # noqa: E402 +import menus # noqa: E402 +import ooyalahelper # noqa: E402 +import categories # noqa: E402 + +_url = sys.argv[0] +_handle = int(sys.argv[1]) +addonname = addon.getAddonInfo('name') +addonPath = xbmcaddon.Addon().getAddonInfo("path") +fanart = os.path.join(addonPath, 'fanart.jpg') + + +def router(paramstring): + """ + Router function that calls other functions + depending on the provided paramstring + :param paramstring: + """ + params = dict(parse_qsl(paramstring)) + if params: + if params['action'] == 'listcategories': + if params['category'] == 'Live Matches': + menus.make_live_list(params) + elif params['category'] == 'Videos': + menus.make_video_list(params) + elif params['category'] == 'Settings': + addon.openSettings() + elif params['action'] == 'listvideos': + play.play_video(params) + elif params['action'] == 'cleartoken': + ooyalahelper.clear_token() + else: + categories.list_categories() + + +if __name__ == '__main__': + if addon.getSetting('firstrun') == 'true': + xbmcgui.Dialog().ok(addonname, ('Please enter your My Football Live ' + 'Pass (Telstra ID) username and ' + 'password to access the content ' + 'in this service.')) + addon.openSettings() + addon.setSetting('firstrun', 'false') + router(sys.argv[2][1:]) diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..99ebf19e8bb9929ea4691988dd14c1a09b6812c4 GIT binary patch literal 94229 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]`R1+bK^E_yGGG&ms!Jm^~Fu*;_`+`LDTR7h(?NdBtQKVe1% zy`>@mwBM@~u6Z&JI5IM>HN*^tK!(b9TQ>4kKKNx}%)yf}uy*-{GWC*lzhu z#cn1>Q$K(D2I*()XtU!9_I~U^$gwXKgm+wjkl|s3Mk0|)bax$@5K1`sT~7hDPn3Mj z;P)^y^gLOsutZr>H{etc=Yd=I{C3PBU}L7)^L_Y!Nt=nz+Fa;B)jpcn*0R}SVp0ckpRBCAPw5GwCjfp? zJIAI0Q|J@noOAHkK)Y!d|E#XB;D6?>{+pJ^M^y5U&4MM^RA|z|gZs>k%080K6GqCVK=!b-nf9CtL6>NAFHT~v9q?%v7@(!HIn<`8{qD@L0N+{%@$poh;c0b{H6f|CWUn7z3h!bMtTb zv(m4)e?ut|u#o>ow$8r|1NLl&;|~2T>BF7-|2&fZ&CtjH`^d%0TQqcjV!%niUa1-o OFmC9ZUi+krjQt-SfiGJC literal 0 HcmV?d00001 diff --git a/resources/__init__.py b/resources/__init__.py new file mode 100644 index 0000000..b93054b --- /dev/null +++ b/resources/__init__.py @@ -0,0 +1 @@ +# Dummy file to make this directory a package. diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml new file mode 100644 index 0000000..b6657ac --- /dev/null +++ b/resources/language/English/strings.xml @@ -0,0 +1,14 @@ + + + Telstra Live Pass + Streaming Settings + Debugging + Settings + + firstrun + Remove stored login ticket + Live Match Stream Quality + Replay Stream Quality + Telstra ID Username + Telstra ID Password + diff --git a/resources/lib/__init__.py b/resources/lib/__init__.py new file mode 100644 index 0000000..b93054b --- /dev/null +++ b/resources/lib/__init__.py @@ -0,0 +1 @@ +# Dummy file to make this directory a package. diff --git a/resources/lib/categories.py b/resources/lib/categories.py new file mode 100644 index 0000000..2dfe74f --- /dev/null +++ b/resources/lib/categories.py @@ -0,0 +1,25 @@ +import xbmcgui +import xbmcplugin +import config +import sys +from aussieaddonscommon import utils + +_handle = int(sys.argv[1]) +_url = sys.argv[0] + + +def list_categories(): + try: + listing = [] + categories = config.CATEGORIES + for category in categories: + li = xbmcgui.ListItem(category) + urlString = '{0}?action=listcategories&category={1}' + url = urlString.format(_url, category) + is_folder = True + listing.append((url, li, is_folder)) + + xbmcplugin.addDirectoryItems(_handle, listing, len(listing)) + xbmcplugin.endOfDirectory(_handle) + except Exception: + utils.handle_error('Unable to display categories') diff --git a/resources/lib/classes.py b/resources/lib/classes.py new file mode 100644 index 0000000..1f18d98 --- /dev/null +++ b/resources/lib/classes.py @@ -0,0 +1,76 @@ +import datetime +import time +import urlparse +import unicodedata +import urllib + + +class Video(): + def __init__(self): + self.video_id = None + self.thumb = None + self.title = None + self.live = None + self.time = None + self.desc = None + self.dummy = None + self.account_id = None + self.url = None + self.home = None + self.away = None + self.ooyala_id = None + self.start_date = None + + def make_kodi_url(self): + d = self.__dict__ + for key, value in d.iteritems(): + if isinstance(value, unicode): + d[key] = unicodedata.normalize('NFKD', value).encode('ascii', + 'ignore') + url = '' + if d['thumb']: + d['thumb'] = urllib.quote_plus(d['thumb']) + for item in d.keys(): + url += '&{0}={1}'.format(item, d[item]) + return url + + def parse_kodi_url(self, url): + params = urlparse.parse_qsl(url) + for item in params.keys(): + setattr(self, item, urllib.unquote_plus(params[item])) + + def parse_params(self, params): + for item in params.keys(): + setattr(self, item, urllib.unquote_plus(params[item])) + + def get_live_title(self): + if self.home and self.away: + return '[COLOR green][LIVE NOW][/COLOR] {0} v {1}'.format( + self.home, self.away) + + def get_airtime(self): + try: + delta = ((time.mktime(time.localtime()) - + time.mktime(time.gmtime())) / 3600) + if time.localtime().tm_isdst: + delta += 1 + ts_format = "%Y-%m-%dT%H:%M:%S+00:00" + ts = datetime.datetime.fromtimestamp( + time.mktime(time.strptime(self.start_date, ts_format))) + ts += datetime.timedelta(hours=delta) + return ts.strftime("%A %d %b @ %I:%M %p").replace(' 0', ' ') + except OverflowError: + return timestamp + + def make_time_string(self): + try: + timestamp = time.mktime(time.strptime(self.start_date, + '%Y-%m-%dT%H:%M:%S+00:00')) + video.date = datetime.date.fromtimestamp(timestamp) + except Exception: + pass + + def get_upcoming_title(self): + if self.home and self.away: + return '[COLOR red][Upcoming][/COLOR] {0} v {1} - {2}'.format( + self.home, self.away, self.get_airtime()) diff --git a/resources/lib/comm.py b/resources/lib/comm.py new file mode 100644 index 0000000..db379a3 --- /dev/null +++ b/resources/lib/comm.py @@ -0,0 +1,75 @@ +import classes +import config +import json + +from aussieaddonscommon import utils +from aussieaddonscommon import session + + +def fetch_url(url, headers=None): + """ + HTTP GET on url, remove byte order mark + """ + with session.Session() as sess: + if headers: + sess.headers = headers + resp = sess.get(url) + return resp.text.encode("utf-8") + + +def list_videos(params): + data = json.loads(fetch_url(config.VIDEOS_URL)) + listing = [] + for video in data: + v = classes.Video() + v.title = video.get('name') + v.desc = video.get('name') + v.thumb = video.get('poster_small').get('url') + v.fanart = video.get('poster').get('url') + v.video_id = video.get('video_id') + v.account_id = video.get('account_id') + listing.append(v) + return listing + + +def list_live(params): + data = json.loads(fetch_url(config.HOME_URL)) + listing = [] + for match in data.get('upcoming_matches'): + match_data = match.get('match') + if not match: + continue + if match_data.get('status') == 'FullTime': + continue + broadcasters = match_data.get('broadcasters') + if not broadcasters: + continue + v = classes.Video() + v.home = match_data.get('home_team').get('name') + v.away = match_data.get('away_team').get('name') + if match_data.get('status') == 'Live': + v.live = True + v.title = v.get_live_title() + for broadcast in broadcasters: + if 'Telstra' in broadcast.get('name'): + v.ooyala_id = broadcast.get('stream_name') + #v.thumb = broadcast.get('logo') + break + else: + v.dummy = True + v.start_date = match_data.get('start_date') + v.title = v.get_upcoming_title() + listing.append(v) + return listing + + +def get_stream_url(account_id, video_id): + policy = config.BC_POLICYS[account_id] + bc_url = config.BC_URL.format(account_id, video_id) + data = json.loads(fetch_url(bc_url, {'BCOV-POLICY': policy})) + for source in data.get('sources'): + ext_ver = source.get('ext_x_version') + src = source.get('src') + if ext_ver == '4' and src: + if src.startswith('https'): + return src diff --git a/resources/lib/config.py b/resources/lib/config.py new file mode 100644 index 0000000..eeea1c4 --- /dev/null +++ b/resources/lib/config.py @@ -0,0 +1,119 @@ +# flake8: noqa + +NAME = 'Soccer Live' +ADDON_ID = 'plugin.video.soccer-live' + +GITHUB_API_URL = 'https://api.github.com/repos/aussieaddons/plugin.video.soccer-live' +ISSUE_API_URL = GITHUB_API_URL + '/issues' +ISSUE_API_AUTH = 'eGJtY2JvdDo1OTQxNTJjMTBhZGFiNGRlN2M0YWZkZDYwZGQ5NDFkNWY4YmIzOGFj' +GIST_API_URL = 'https://api.github.com/gists' + +MAX_LIVEQUAL = 4 +MAX_REPLAYQUAL = 7 + +CONFIG_URL = 'https://gateway.ffa.football/mobile/hub/config' + +HOME_URL = 'https://gateway.ffa.football/mobile/hub/home?preferences=aleague,socceroos,matildas,wleague,yleague,ffacup,npl' + +VIDEOS_URL = 'https://gateway.ffa.football/content/aleague/videos?offset=0&limit=50' + +BC_URL = 'https://edge.api.brightcove.com/playback/v1/accounts/{0}/videos/{1}' + +BC_POLICYS = {'5519514577001': 'BCpkADawqM0j7AXGHFi_Dwx883WcrB6UvwJHuWlGKbtxY-isLlgM48Ck0TfWgJvo38YKyAebRSKVM2eZ3aLBomKWx63vH4QEcFJqWBSCmidqcI2CJxSNYKkaW3S0KlPhQg2KcNx0oA_1VjAK', + '5519514578001': 'BCpkADawqM0r9EEGoAc_vGhRKzA9LNT8kbAUfWYmdoVVB1NlYGrCt58_3Ky50L_rVj4gcYjA4WWG7DP1lA4LBDrqik98PdHN9ivVl9mQ8l2jzkf7nQqeTFB-5FKxmuhBDZ5_9GwcNDJFO-V7', + '5519514571001': 'BCpkADawqM3SGkvPiiweCR4BrANOi6Wu3dtzOIZVrDGY_XcQuOAVEU5_ubheHLKzCmBBBcq3IsAyhWrKss_xIMIJj_hrIEovLg2xNmFDyR00ojao3McEmOMDwk36iK5v-9xVbkbCWabCNRaZ', + '5519514572001': 'BCpkADawqM3qdGnXQkUk1OiqcwLAl5pM5hbynJDi52VVRMyiWZqc0dPaCu55y1nJmH49BFSJNHj1lveEVvXH_BdX8G0MaP4Tb0wKk0GOuUU-q0P9eQZNZg52R_S7XkS4WhvxYZLbtLMzpQJs', + '5519514573001': 'BCpkADawqM0a2uwu4YiOyVlm9L9HcSCW8tFT3KhCYS-qD2vgsyy7SWALmQF6CsS8SjrMzsPT2qsrz8W4U5HItDvXvqSngrQftPe04YvJ3lVxvNl8TG5T3qWSzqtQHZxeo1Oo2gPMjXNGsxXt', + '5519514574001': 'BCpkADawqM03yDM88JKXMgU0sWi9CCFGZI-0W2a2DsKW3dLR8pl60Lp8w5mZ2KFoX4VRaKf2C0EAR2HTODKU-31SQL1sPadUHcCyitDS1nMfTGplN6nCobcx_eaI2y7vP0ZfM0roCwRifhdN', + '5519514575001': 'BCpkADawqM1qoT9hdCPQapbHacGAuZkTbXHrzsZrcJmLeO1O8iw4NxjWC5nr3IDfhZKX4BLcJxEYni79JlYTf96eC3tx0ldTNYYbL8Sk8EljSt_4j8Zc05YJ7PdHOw907E1pZl0Z2nzHfOcz', + '5472387882001': 'BCpkADawqM27fXg9qQmpIm67ZxQq_PcLYENoWW-3FiLR1QmXph9PM2HuYw_nkTvnCRU3djpjWHJ81IBsw5fRCYFtuFTAJoch_wxrqr1DsPpieYAv-3sXPakRUfMPbPUbqTYKF5jHSYyENMzX'} + +USER_AGENT = 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; m8 Build/MOB31K)' + +USER_AGENT_LONG = 'Mozilla/5.0 (Linux; Android 6.0; HTC One_M8 Build/MRA58K.H15; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36' + +OOYALA_PCODE = 'xoNG0yOk4f4VR8pLKAKNukJ-gdEr' + +OOYALA_AUTH_URL = 'http://player.ooyala.com/sas/player_api/v1/authorization/embed_code/{0}/{1}?device=android_html&domain=http%3A%2F%2Fwww.ooyala.com&supportedFormats=dash%2Cakamai_hd2_vod_hls%2Cmp4%2Cm3u8%2Chls%2Cakamai_hd2_hls' + + +OAUTH_HEADERS = {'User-Agent': 'okhttp/3.10.0', + 'Accept-Encoding': 'gzip'} + +OAUTH_DATA = {'client_id': 'yGQTEDLGiWeVBogNzKuZAAt6x1yVk3Ot', + 'client_secret': 'zsbhQBtJ9Towbac7', + 'grant_type': 'client_credentials', + 'scope': 'MEDIA-ENTITLEMENTS-API MEDIA-PURCHASE-API', + 'x-user-idp': 'PARTNER'} + +OAUTH_URL = 'https://tapi.telstra.com/v1/media-entitlements/oauth/token' + +ENTITLEMENTS_URL = 'https://tapi.telstra.com/v1/media-entitlements/entitlements?tenantid=ffa' + +SPC_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', + 'Accept-Encoding': 'gzip, ' + 'deflate', + 'Accept-Language': 'en-AU,en-US;q=0.9', + 'User-Agent': USER_AGENT_LONG, + 'X-Requested-With': 'com.ffa.hal'} + +SPC_URL = 'http://hub.telstra.com.au/sp2018-ffa-app?tpUID={0}&offerId=45d09e09-6472-43fa-9f24-d328d9b25ec7&type=SportPassConfirmation&device=mobile&cid=FFA_App' + +SSO_PARAMS = {'redirect_uri': 'https://hub.telstra.com.au/offers/content/cached/callback.html', + 'response_type': 'id_token token', + 'scope': 'openid email profile phone telstra.user.sso.profile'} + +SSO_URL = 'https://api.telstra.com/v1/sso/auth' + + + + +CATEGORIES = ['Live Matches', + 'Videos', + 'Settings'] + + +SIGNON_HEADERS = {'Host': 'signon.telstra.com', + 'Connection': 'keep-alive', + 'Cache-Control': 'max-age=0', + 'Origin': 'https://signon.telstra.com', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; HTC One_M8 Build/MRA58K.H15; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Referer': 'https://signon.telstra.com/login?goto=https%3A%2F%2Fsignon.telstra.com%2Ffederation%2Fsaml2%3FSPID%3Dtelstramedia&gotoNoTok=', + 'Accept-Encoding': 'gzip, deflate', + 'Accept-Language': 'en-AU,en-US;q=0.8'} + +SIGNON_URL = 'https://signon.telstra.com/login' + +SIGNON_DATA = {'goto': 'https://signon.telstra.com/federation/saml2?SPID=telstramedia', 'gotoOnFail': '', 'username': None, 'password': None} + +OFFERS_URL = 'https://api.telstra.com/v1/media-products/catalogues/media/offers?category=ffa' + +HUB_URL = 'http://hub.telstra.com.au/sp2017-netball-app' + +SSO_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', + 'Accept-Encoding': 'gzip, ' + 'deflate', + 'Accept-Language': 'en-AU,en-US;q=0.9', + 'Cache-Control': 'max-age=0', + 'Connection': 'keep-alive', + 'Referer': 'https://signon.telstra.com.au/login?goto=https%3A%2F%2Fapi.telstra.com%2Fv1%2Fsso%2Fidpcallback%3Fcbs%3DeyJhbGciOiJIUzI1NiJ9.eyJjYWxsYmFja19zdGF0ZSI6IjEyMjcyMDQ3LWU3N2ItNGRiZC1hNGZiLTBlYTcwMDMyYmRlMSIsImF1ZCI6InJhYSIsImV4cCI6MTUyMDczNTMyMTk0OCwiaWF0IjoxNTIwNjQ4OTIxOTQ4fQ.-I05HQE9eIpRS0LLSYB_pJ4iVKZZzyziVYarvjCe_2o%26app_name%3DOne%20Place%20portal', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': USER_AGENT_LONG, + 'X-Requested-With': 'au.com.netball'} + +MEDIA_ORDER_HEADERS = {'Content-Type': 'application/json', + 'Accept': 'application/json, text/plain, */*', + 'Host': 'api.telstra.com', + 'Connection': 'keep-alive', + 'Origin': 'https://hub.telstra.com.au', + 'User-Agent': USER_AGENT_LONG, + 'Accept-Encoding': 'gzip, deflate', + 'Accept-Language': 'en-AU,en-US;q=0.8', + 'X-Requested-With': 'au.com.netball'} + +MEDIA_ORDER_URL = 'https://api.telstra.com/v1/media-commerce/orders' + +MEDIA_ORDER_JSON = '{{"serviceId":"{0}","serviceType":"MSISDN","offer":{{"id":"{1}"}},"pai":"{2}"}}' diff --git a/resources/lib/menus.py b/resources/lib/menus.py new file mode 100644 index 0000000..e1de9f8 --- /dev/null +++ b/resources/lib/menus.py @@ -0,0 +1,59 @@ +import xbmcgui +import xbmcplugin +import xbmcaddon +import comm +import sys +from aussieaddonscommon import utils + +_url = sys.argv[0] +_handle = int(sys.argv[1]) +addon_path = xbmcaddon.Addon().getAddonInfo("path") + + +def make_video_list(params): + """ + Build video listing for Kodi + """ + try: + listing = [] + videos = comm.list_videos(params) + + for v in videos: + li = xbmcgui.ListItem(label=v.title, + iconImage=v.thumb, + thumbnailImage=v.thumb) + url = '{0}?action=listvideos{1}'.format(_url, v.make_kodi_url()) + is_folder = False + li.setProperty('IsPlayable', 'true') + li.setInfo('video', {'plot': v.desc, 'plotoutline': v.desc}) + listing.append((url, li, is_folder)) + + xbmcplugin.addDirectoryItems(_handle, listing, len(listing)) + xbmcplugin.endOfDirectory(_handle) + except Exception: + utils.handle_error('Unable to display matches') + + +def make_live_list(params): + """ + Build live match listing for Kodi + """ + try: + listing = [] + videos = comm.list_live(params) + + for v in videos: + li = xbmcgui.ListItem(label=v.title, + iconImage=v.thumb, + thumbnailImage=v.thumb) + url = '{0}?action=listvideos{1}'.format(_url, v.make_kodi_url()) + is_folder = False + if not v.dummy: + li.setProperty('IsPlayable', 'true') + li.setInfo('video', {'plot': v.desc, 'plotoutline': v.desc}) + listing.append((url, li, is_folder)) + + xbmcplugin.addDirectoryItems(_handle, listing, len(listing)) + xbmcplugin.endOfDirectory(_handle, cacheToDisc=False) + except Exception: + utils.handle_error('Unable to display matches') diff --git a/resources/lib/ooyalahelper.py b/resources/lib/ooyalahelper.py new file mode 100644 index 0000000..41764ba --- /dev/null +++ b/resources/lib/ooyalahelper.py @@ -0,0 +1,186 @@ +import urllib +import json +import base64 +import config +import re +import requests +import xbmcaddon +import telstra_auth + +from aussieaddonscommon.exceptions import AussieAddonsException +from aussieaddonscommon import session +from aussieaddonscommon import utils + +try: + import StorageServer +except: + utils.log("script.common.plugin.cache not found!") + import storageserverdummy as StorageServer +cache = StorageServer.StorageServer(config.ADDON_ID, 1) +sess = session.Session(force_tlsv1=False) +addon = xbmcaddon.Addon() +username = addon.getSetting('LIVE_USERNAME') +password = addon.getSetting('LIVE_PASSWORD') + + +def clear_ticket(): + """ + Remove stored ticket from cache storage + """ + cache.delete('SOCCERTICKET') + utils.dialog_message('Login token removed') + + +def get_user_ticket(): + """ + send user login info and retrieve ticket for session + """ + stored_ticket = cache.get('SOCCERTICKET') + if stored_ticket != '': + utils.log('Using ticket: {0}******'.format(stored_ticket[:-6])) + return stored_ticket + else: + ticket = telstra_auth.get_free_token(username, password) + cache.set('SOCCERTICKET', ticket) + return ticket + + +def get_embed_token(user_token, video_id): + """ + send our user token to get our embed token, including api key + """ + url = config.EMBED_TOKEN_URL.format(video_id) + sess.headers.update({'X-YinzCam-Ticket': user_token, + 'Accept': 'application/json'}) + try: + req = sess.get(url) + data = req.text + json_data = json.loads(data) + if json_data.get('ErrorCode') is not None: + raise AussieAddonsException() + video_token = json_data.get('VideoToken') + except requests.exceptions.HTTPError as e: + utils.log('Error getting embed token. ' + 'Response: {0}'.format(e.response.text)) + cache.delete('NETBALLTICKET') + if e.response.status_code == 401: + raise AussieAddonsException('Login token has expired, ' + 'please try again.') + else: + raise e + return urllib.quote(video_token) + + +def get_secure_token(secure_url, videoId): + """ + send our embed token back with a few other url encoded parameters + """ + res = sess.get(secure_url) + data = res.text + try: + parsed_json = json.loads(data) + token = (parsed_json['authorization_data'][videoId] + ['streams'][0]['url']['data']) + except KeyError: + utils.log('Video ID: {0}'.format(videoId)) + utils.log('Parsed json data: {0}'.format(parsed_json)) + try: + auth_msg = parsed_json['authorization_data'][videoId]['message'] + if auth_msg == 'unauthorized location': + country = parsed_json['user_info']['country'] + raise AussieAddonsException('Unauthorised location for ' + 'streaming. ' + 'Detected location is: {0}. ' + 'Please check VPN/smart DNS ' + 'settings ' + ' and try again'.format(country)) + except Exception as e: + raise e + return base64.b64decode(token) + + +def get_m3u8_streams(secure_token_url): + """ + fetch our m3u8 file which contains streams of various qualities + """ + res = sess.get(secure_token_url) + data = res.text.splitlines() + return data + + +def parse_m3u8_streams(data, live, secure_token_url): + """ + Parse the retrieved m3u8 stream list into a list of dictionaries + then return the url for the highest quality stream. Different + handling is required of live m3u8 files as they seem to only contain + the destination filename and not the domain/path. + """ + if live: + qual = int(addon.getSetting('LIVEQUALITY')) + if qual == config.MAX_LIVEQUAL: + qual = -1 + # fix for values too high from previous API config + if qual > config.MAX_LIVEQUAL: + addon.setSetting('LIVEQUALITY', str(config.MAX_LIVEQUAL)) + qual = -1 + else: + qual = int(addon.getSetting('REPLAYQUALITY')) + if qual == config.MAX_REPLAYQUAL: + qual = -1 + # fix for values too high from previous API config + if qual > config.MAX_REPLAYQUAL: + addon.setSetting('REPLAYQUALITY', str(config.MAX_REPLAYQUAL)) + qual = -1 + + m3u_list = [] + base_url = secure_token_url[:secure_token_url.rfind('/') + 1] + base_domain = secure_token_url[:secure_token_url.find('/', 8) + 1] + m3u8_lines = iter(data) + for line in m3u8_lines: + stream_inf = '#EXT-X-STREAM-INF:' + if line.startswith(stream_inf): + line = line[len(stream_inf):] + else: + continue + + csv_list = re.split(',(?=(?:(?:[^"]*"){2})*[^"]*$)', line) + linelist = [i.split('=') for i in csv_list] + + uri = next(m3u8_lines) + + if uri.startswith('/'): + linelist.append(['URL', base_domain + uri]) + elif uri.find('://') == -1: + linelist.append(['URL', base_url + uri]) + else: + linelist.append(['URL', uri]) + m3u_list.append(dict((i[0], i[1]) for i in linelist)) + sorted_m3u_list = sorted(m3u_list, key=lambda k: int(k['BANDWIDTH'])) + try: + stream = sorted_m3u_list[qual]['URL'] + except IndexError as e: + utils.log('Quality setting: {0}'.format(qual)) + utils.log('Sorted m3u8 list: {0}'.format(sorted_m3u_list)) + raise e + return stream + + +def get_m3u8_playlist(video_id): + """ Main function to call other functions that will return us our m3u8 HLS + playlist as a string, which we can then write to a file for Kodi + to use""" + #login_token = get_user_ticket() + #embed_token = get_embed_token(login_token, video_id) + get_user_ticket() + authorize_url = config.OOYALA_AUTH_URL.format(config.OOYALA_PCODE, + video_id) + secure_token_url = get_secure_token(authorize_url, video_id) + + if 'chunklist.m3u8' in secure_token_url: + return secure_token_url + + m3u8_data = get_m3u8_streams(secure_token_url) + m3u8_playlist_url = parse_m3u8_streams(m3u8_data, + live=True, + secure_token_url=secure_token_url) + return m3u8_playlist_url diff --git a/resources/lib/play.py b/resources/lib/play.py new file mode 100644 index 0000000..4d8c4eb --- /dev/null +++ b/resources/lib/play.py @@ -0,0 +1,40 @@ +import classes +import comm +import ooyalahelper +import sys +import xbmcaddon +import xbmcgui +import xbmcplugin +from aussieaddonscommon import utils + +addon = xbmcaddon.Addon() +_handle = int(sys.argv[1]) + + +def play_video(params): + """ + Play a video by the provided path. + :param path: str + """ + + try: + v = classes.Video() + v.parse_params(params) + if v.dummy == 'True': + xbmcgui.Dialog().ok( + 'Dummy item', + 'This item is not playable, it is used only to display ' + 'the upcoming schedule. Please check back once the match ' + 'has started. Playable matches will have "LIVE NOW" in ' + 'green next to the title.') + return + if v.live == 'True': + v.url = ooyalahelper.get_m3u8_playlist(v.ooyala_id) + else: + v.url = comm.get_stream_url(v.account_id, v.video_id) + play_item = xbmcgui.ListItem(path=v.url, + iconImage=v.thumb, + thumbnailImage=v.thumb) + xbmcplugin.setResolvedUrl(_handle, True, listitem=play_item) + except Exception: + utils.handle_error('Unable to play video') diff --git a/resources/lib/storageserverdummy.py b/resources/lib/storageserverdummy.py new file mode 100644 index 0000000..df2fc85 --- /dev/null +++ b/resources/lib/storageserverdummy.py @@ -0,0 +1,30 @@ +''' + StorageServer override. + Version: 1.0 +''' + + +class StorageServer: + def __init__(self, table, timeout=24): + return None + + def cacheFunction(self, funct=False, *args): + return funct(*args) + + def set(self, name, data): + return "" + + def get(self, name): + return "" + + def setMulti(self, name, data): + return "" + + def getMulti(self, name, items): + return "" + + def lock(self, name): + return False + + def unlock(self, name): + return False diff --git a/resources/lib/telstra_auth.py b/resources/lib/telstra_auth.py new file mode 100644 index 0000000..245772b --- /dev/null +++ b/resources/lib/telstra_auth.py @@ -0,0 +1,177 @@ +import binascii +import config +import json +import os +import re +import requests +import urlparse +import uuid +import xbmcgui + +from aussieaddonscommon.exceptions import AussieAddonsException +from aussieaddonscommon import session as custom_session +from aussieaddonscommon import utils + + +class TelstraAuthException(AussieAddonsException): + """Telstra Auth exception + This exception can be thrown with the reportable arg set which can + determine whether or not it is allowed to be sent as an automatic + error report + """ + pass + + +def get_free_token(username, password): + """ + Obtain a valid token from Telstra/Yinzcam, will be used to make + requests for Ooyala embed tokens + """ + session = custom_session.Session(force_tlsv1=False) + prog_dialog = xbmcgui.DialogProgress() + prog_dialog.create('Logging in with Telstra ID') + + # Send our first login request to Yinzcam, recieve (unactivated) ticket + prog_dialog.update(1, 'Obtaining oauth token') + userid = uuid.uuid4() + config.OAUTH_DATA.update({'x-user-id': userid}) + oauth_resp = session.post(config.OAUTH_URL, + data=config.OAUTH_DATA) + oauth_json = json.loads(oauth_resp.text) + access_token = oauth_json.get('access_token') + session.headers = {} + session.headers.update( + {'Authorization': 'Bearer {0}'.format(access_token)}) + + # Check entitlements (not sure if needed) + session.get(config.ENTITLEMENTS_URL) + + prog_dialog.update(16, 'Getting SSO Client ID') + # GET to our spc url and receive SSO client ID + session.headers = config.SPC_HEADERS # check if needed + spc_url = config.SPC_URL.format(userid) + spc_resp = session.get(spc_url) + sso_token_match = re.search('ssoClientId = "(\w+)"', spc_resp.text) + try: + sso_token = sso_token_match.group(1) + except AttributeError as e: + utils.log('SPC login response: {0}'.format(spc_resp.text)) + raise e + + # Sign in to telstra.com with our SSO client id to get the url + # for retrieving the bearer token for media orders + prog_dialog.update(33, 'Signing on to telstra.com') + sso_params = config.SSO_PARAMS + sso_params.update({'client_id': sso_token, + 'state': binascii.b2a_hex(os.urandom(16)), + 'nonce': binascii.b2a_hex(os.urandom(16))}) + + sso_auth_resp = session.get(config.SSO_URL, params=sso_params) + sso_url = dict(urlparse.parse_qsl( + urlparse.urlsplit(sso_auth_resp.url)[3])).get('goto') + + # login to telstra.com.au and get our BPSESSION cookie + session.headers.update(config.SIGNON_HEADERS) + signon_data = config.SIGNON_DATA + signon_data = {'username': username, 'password': password, 'goto': sso_url} + signon = session.post(config.SIGNON_URL, + data=signon_data, + allow_redirects=False) + bp_session = session.cookies.get_dict().get('BPSESSION') + + # check signon is valid (correct username/password) + + signon_pieces = urlparse.urlsplit(signon.headers.get('Location')) + signon_query = dict(urlparse.parse_qsl(signon_pieces.query)) + + utils.log('Sign-on result: %s' % signon_query) + + if 'errorcode' in signon_query: + if signon_query['errorcode'] == '0': + raise TelstraAuthException('Please enter your username ' + 'in the settings') + if signon_query['errorcode'] == '1': + raise TelstraAuthException('Please enter your password ' + 'in the settings') + if signon_query['errorcode'] == '2': + raise TelstraAuthException('Please enter your username and ' + 'password in the settings') + if signon_query['errorcode'] == '3': + raise TelstraAuthException('Invalid Telstra ID username/password. ' + 'Please check your username and ' + 'password in the settings') + + # Use BPSESSION cookie to ask for bearer token + sso_headers = config.SSO_HEADERS + sso_headers.update({'Cookie': 'BPSESSION={0}'.format(bp_session)}) + session.headers = sso_headers + sso_token_resp = session.get(sso_url) + bearer_token = dict(urlparse.parse_qsl( + urlparse.urlsplit(sso_token_resp.url)[4]))['access_token'] + + # First check if there are any eligible services attached to the account + prog_dialog.update(50, 'Determining eligible services') + offer_id = dict(urlparse.parse_qsl( + urlparse.urlsplit(spc_url)[3]))['offerId'] + media_order_headers = config.MEDIA_ORDER_HEADERS + media_order_headers.update( + {'Authorization': 'Bearer {0}'.format(bearer_token)}) + session.headers = media_order_headers + try: + offers = session.get(config.OFFERS_URL) + except requests.exceptions.HTTPError as e: + if e.response.status_code == 404: + message = json.loads(e.response.text).get('userMessage') + message += (' Please visit {0} '.format(config.HUB_URL) + + 'for further instructions to link your mobile ' + 'service to the supplied Telstra ID') + raise TelstraAuthException(message) + else: + raise TelstraAuthException(e.response.status_code) + try: + offer_data = json.loads(offers.text) + offers_list = offer_data['data']['offers'] + ph_no = None + for offer in offers_list: + if offer.get('name') != 'My Football Live Pass': + continue + data = offer.get('productOfferingAttributes') + ph_no = [x['value'] for x in data if x['name'] == 'ServiceId'][0] + if not ph_no: + raise TelstraAuthException( + 'Unable to determine if you have any eligible services. ' + 'Please ensure there is an eligible service linked to ' + 'your Telstra ID to redeem the free offer. Please visit ' + '{0} for further instructions'.format(config.HUB_URL)) + except Exception as e: + raise e + + # 'Order' the subscription package to activate the service + prog_dialog.update(66, 'Activating live pass on service') + order_data = config.MEDIA_ORDER_JSON.format(ph_no, offer_id, userid) + print order_data + order = session.post(config.MEDIA_ORDER_URL, data=order_data) + + # check to make sure order has been placed correctly + if order.status_code == 201: + try: + order_json = json.loads(order.text) + status = order_json['data'].get('status') == 'COMPLETE' + if status: + utils.log('Order status complete') + except: + utils.log('Unable to check status of order, continuing anyway') + + # Confirm activation + prog_dialog.update(83, 'Confirming activation') + session.headers = {} + session.headers.update( + {'Authorization': 'Bearer {0}'.format(access_token)}) + confirm = json.loads(session.get(config.ENTITLEMENTS_URL).text) + if len(confirm.get('entitlements')) < 1: + raise AussieAddonsException('Telstra ID activation failed') + + session.close() + prog_dialog.update(100, 'Finished!') + prog_dialog.close() + return userid diff --git a/resources/settings.xml b/resources/settings.xml new file mode 100644 index 0000000..993bf70 --- /dev/null +++ b/resources/settings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file