├── .gitignore
├── LICENSE.txt
├── README.md
├── addic7ed_dict.txt
├── addon.xml
├── changelog.txt
├── icon.png
├── logo.png
├── resources
├── language
│ └── English
│ │ └── strings.po
└── lib
│ ├── Addic7edUtilities.py
│ └── __init__.py
└── service.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore mac dir files
2 | .DS_Store
3 | */.DS_Store
4 |
5 | # Ignore python files
6 | *.pyc
7 | *.pyo
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | GNU GENERAL PUBLIC LICENSE
3 | Version 2, June 1991
4 |
5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7 | Everyone is permitted to copy and distribute verbatim copies
8 | of this license document, but changing it is not allowed.
9 |
10 | Preamble
11 |
12 | The licenses for most software are designed to take away your
13 | freedom to share and change it. By contrast, the GNU General Public
14 | License is intended to guarantee your freedom to share and change free
15 | software--to make sure the software is free for all its users. This
16 | General Public License applies to most of the Free Software
17 | Foundation's software and to any other program whose authors commit to
18 | using it. (Some other Free Software Foundation software is covered by
19 | the GNU Library General Public License instead.) You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | this service if you wish), that you receive source code or can get it
26 | if you want it, that you can change the software or use pieces of it
27 | in new free programs; and that you know you can do these things.
28 |
29 | To protect your rights, we need to make restrictions that forbid
30 | anyone to deny you these rights or to ask you to surrender the rights.
31 | These restrictions translate to certain responsibilities for you if you
32 | distribute copies of the software, or if you modify it.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must give the recipients all the rights that
36 | you have. You must make sure that they, too, receive or can get the
37 | source code. And you must show them these terms so they know their
38 | rights.
39 |
40 | We protect your rights with two steps: (1) copyright the software, and
41 | (2) offer you this license which gives you legal permission to copy,
42 | distribute and/or modify the software.
43 |
44 | Also, for each author's protection and ours, we want to make certain
45 | that everyone understands that there is no warranty for this free
46 | software. If the software is modified by someone else and passed on, we
47 | want its recipients to know that what they have is not the original, so
48 | that any problems introduced by others will not reflect on the original
49 | authors' reputations.
50 |
51 | Finally, any free program is threatened constantly by software
52 | patents. We wish to avoid the danger that redistributors of a free
53 | program will individually obtain patent licenses, in effect making the
54 | program proprietary. To prevent this, we have made it clear that any
55 | patent must be licensed for everyone's free use or not licensed at all.
56 |
57 | The precise terms and conditions for copying, distribution and
58 | modification follow.
59 |
60 | GNU GENERAL PUBLIC LICENSE
61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
62 |
63 | 0. This License applies to any program or other work which contains
64 | a notice placed by the copyright holder saying it may be distributed
65 | under the terms of this General Public License. The "Program", below,
66 | refers to any such program or work, and a "work based on the Program"
67 | means either the Program or any derivative work under copyright law:
68 | that is to say, a work containing the Program or a portion of it,
69 | either verbatim or with modifications and/or translated into another
70 | language. (Hereinafter, translation is included without limitation in
71 | the term "modification".) Each licensee is addressed as "you".
72 |
73 | Activities other than copying, distribution and modification are not
74 | covered by this License; they are outside its scope. The act of
75 | running the Program is not restricted, and the output from the Program
76 | is covered only if its contents constitute a work based on the
77 | Program (independent of having been made by running the Program).
78 | Whether that is true depends on what the Program does.
79 |
80 | 1. You may copy and distribute verbatim copies of the Program's
81 | source code as you receive it, in any medium, provided that you
82 | conspicuously and appropriately publish on each copy an appropriate
83 | copyright notice and disclaimer of warranty; keep intact all the
84 | notices that refer to this License and to the absence of any warranty;
85 | and give any other recipients of the Program a copy of this License
86 | along with the Program.
87 |
88 | You may charge a fee for the physical act of transferring a copy, and
89 | you may at your option offer warranty protection in exchange for a fee.
90 |
91 | 2. You may modify your copy or copies of the Program or any portion
92 | of it, thus forming a work based on the Program, and copy and
93 | distribute such modifications or work under the terms of Section 1
94 | above, provided that you also meet all of these conditions:
95 |
96 | a) You must cause the modified files to carry prominent notices
97 | stating that you changed the files and the date of any change.
98 |
99 | b) You must cause any work that you distribute or publish, that in
100 | whole or in part contains or is derived from the Program or any
101 | part thereof, to be licensed as a whole at no charge to all third
102 | parties under the terms of this License.
103 |
104 | c) If the modified program normally reads commands interactively
105 | when run, you must cause it, when started running for such
106 | interactive use in the most ordinary way, to print or display an
107 | announcement including an appropriate copyright notice and a
108 | notice that there is no warranty (or else, saying that you provide
109 | a warranty) and that users may redistribute the program under
110 | these conditions, and telling the user how to view a copy of this
111 | License. (Exception: if the Program itself is interactive but
112 | does not normally print such an announcement, your work based on
113 | the Program is not required to print an announcement.)
114 |
115 | These requirements apply to the modified work as a whole. If
116 | identifiable sections of that work are not derived from the Program,
117 | and can be reasonably considered independent and separate works in
118 | themselves, then this License, and its terms, do not apply to those
119 | sections when you distribute them as separate works. But when you
120 | distribute the same sections as part of a whole which is a work based
121 | on the Program, the distribution of the whole must be on the terms of
122 | this License, whose permissions for other licensees extend to the
123 | entire whole, and thus to each and every part regardless of who wrote it.
124 |
125 | Thus, it is not the intent of this section to claim rights or contest
126 | your rights to work written entirely by you; rather, the intent is to
127 | exercise the right to control the distribution of derivative or
128 | collective works based on the Program.
129 |
130 | In addition, mere aggregation of another work not based on the Program
131 | with the Program (or with a work based on the Program) on a volume of
132 | a storage or distribution medium does not bring the other work under
133 | the scope of this License.
134 |
135 | 3. You may copy and distribute the Program (or a work based on it,
136 | under Section 2) in object code or executable form under the terms of
137 | Sections 1 and 2 above provided that you also do one of the following:
138 |
139 | a) Accompany it with the complete corresponding machine-readable
140 | source code, which must be distributed under the terms of Sections
141 | 1 and 2 above on a medium customarily used for software interchange; or,
142 |
143 | b) Accompany it with a written offer, valid for at least three
144 | years, to give any third party, for a charge no more than your
145 | cost of physically performing source distribution, a complete
146 | machine-readable copy of the corresponding source code, to be
147 | distributed under the terms of Sections 1 and 2 above on a medium
148 | customarily used for software interchange; or,
149 |
150 | c) Accompany it with the information you received as to the offer
151 | to distribute corresponding source code. (This alternative is
152 | allowed only for noncommercial distribution and only if you
153 | received the program in object code or executable form with such
154 | an offer, in accord with Subsection b above.)
155 |
156 | The source code for a work means the preferred form of the work for
157 | making modifications to it. For an executable work, complete source
158 | code means all the source code for all modules it contains, plus any
159 | associated interface definition files, plus the scripts used to
160 | control compilation and installation of the executable. However, as a
161 | special exception, the source code distributed need not include
162 | anything that is normally distributed (in either source or binary
163 | form) with the major components (compiler, kernel, and so on) of the
164 | operating system on which the executable runs, unless that component
165 | itself accompanies the executable.
166 |
167 | If distribution of executable or object code is made by offering
168 | access to copy from a designated place, then offering equivalent
169 | access to copy the source code from the same place counts as
170 | distribution of the source code, even though third parties are not
171 | compelled to copy the source along with the object code.
172 |
173 | 4. You may not copy, modify, sublicense, or distribute the Program
174 | except as expressly provided under this License. Any attempt
175 | otherwise to copy, modify, sublicense or distribute the Program is
176 | void, and will automatically terminate your rights under this License.
177 | However, parties who have received copies, or rights, from you under
178 | this License will not have their licenses terminated so long as such
179 | parties remain in full compliance.
180 |
181 | 5. You are not required to accept this License, since you have not
182 | signed it. However, nothing else grants you permission to modify or
183 | distribute the Program or its derivative works. These actions are
184 | prohibited by law if you do not accept this License. Therefore, by
185 | modifying or distributing the Program (or any work based on the
186 | Program), you indicate your acceptance of this License to do so, and
187 | all its terms and conditions for copying, distributing or modifying
188 | the Program or works based on it.
189 |
190 | 6. Each time you redistribute the Program (or any work based on the
191 | Program), the recipient automatically receives a license from the
192 | original licensor to copy, distribute or modify the Program subject to
193 | these terms and conditions. You may not impose any further
194 | restrictions on the recipients' exercise of the rights granted herein.
195 | You are not responsible for enforcing compliance by third parties to
196 | this License.
197 |
198 | 7. If, as a consequence of a court judgment or allegation of patent
199 | infringement or for any other reason (not limited to patent issues),
200 | conditions are imposed on you (whether by court order, agreement or
201 | otherwise) that contradict the conditions of this License, they do not
202 | excuse you from the conditions of this License. If you cannot
203 | distribute so as to satisfy simultaneously your obligations under this
204 | License and any other pertinent obligations, then as a consequence you
205 | may not distribute the Program at all. For example, if a patent
206 | license would not permit royalty-free redistribution of the Program by
207 | all those who receive copies directly or indirectly through you, then
208 | the only way you could satisfy both it and this License would be to
209 | refrain entirely from distribution of the Program.
210 |
211 | If any portion of this section is held invalid or unenforceable under
212 | any particular circumstance, the balance of the section is intended to
213 | apply and the section as a whole is intended to apply in other
214 | circumstances.
215 |
216 | It is not the purpose of this section to induce you to infringe any
217 | patents or other property right claims or to contest validity of any
218 | such claims; this section has the sole purpose of protecting the
219 | integrity of the free software distribution system, which is
220 | implemented by public license practices. Many people have made
221 | generous contributions to the wide range of software distributed
222 | through that system in reliance on consistent application of that
223 | system; it is up to the author/donor to decide if he or she is willing
224 | to distribute software through any other system and a licensee cannot
225 | impose that choice.
226 |
227 | This section is intended to make thoroughly clear what is believed to
228 | be a consequence of the rest of this License.
229 |
230 | 8. If the distribution and/or use of the Program is restricted in
231 | certain countries either by patents or by copyrighted interfaces, the
232 | original copyright holder who places the Program under this License
233 | may add an explicit geographical distribution limitation excluding
234 | those countries, so that distribution is permitted only in or among
235 | countries not thus excluded. In such case, this License incorporates
236 | the limitation as if written in the body of this License.
237 |
238 | 9. The Free Software Foundation may publish revised and/or new versions
239 | of the General Public License from time to time. Such new versions will
240 | be similar in spirit to the present version, but may differ in detail to
241 | address new problems or concerns.
242 |
243 | Each version is given a distinguishing version number. If the Program
244 | specifies a version number of this License which applies to it and "any
245 | later version", you have the option of following the terms and conditions
246 | either of that version or of any later version published by the Free
247 | Software Foundation. If the Program does not specify a version number of
248 | this License, you may choose any version ever published by the Free Software
249 | Foundation.
250 |
251 | 10. If you wish to incorporate parts of the Program into other free
252 | programs whose distribution conditions are different, write to the author
253 | to ask for permission. For software which is copyrighted by the Free
254 | Software Foundation, write to the Free Software Foundation; we sometimes
255 | make exceptions for this. Our decision will be guided by the two goals
256 | of preserving the free status of all derivatives of our free software and
257 | of promoting the sharing and reuse of software generally.
258 |
259 | NO WARRANTY
260 |
261 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
262 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
263 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
264 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
265 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
266 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
267 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
268 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
269 | REPAIR OR CORRECTION.
270 |
271 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
272 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
273 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
274 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
275 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
276 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
277 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
278 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
279 | POSSIBILITY OF SUCH DAMAGES.
280 |
281 | END OF TERMS AND CONDITIONS
282 | -------------------------------------------------------------------------
283 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | service.subtitles.addic7ed
2 | ==========================
3 |
4 | Addic7ed.com subtitle service plugin for XBMC/Kodi
5 |
6 | Will not work with Frodo or previous versions of XBMC.
7 |
8 | Disclaimer: UNOFFICIAL addon! Not responsible for anything that happens - good, bad, or otherwise if you decide to use this addon.
9 |
10 | Git clone this project into the 'addons' folder.
11 |
--------------------------------------------------------------------------------
/addic7ed_dict.txt:
--------------------------------------------------------------------------------
1 | {'Kitchen Nightmares US': 'Kitchen Nightmares',
2 | 'Cosmos A Space Time Odyssey': 'Cosmos: A Space-Time Odyssey',
3 | 'Greys Anatomy': 'Grey\'s Anatomy',
4 | 'Shameless': 'Shameless (US)',
5 | 'The Americans (2013)': 'The Americans',
6 | 'Once Upon a Time (2011)': 'Once Upon a Time',
7 | 'Castle (2009)': 'Castle',
8 | 'Marvel\'s Daredevil': 'Daredevil',
9 | 'House of Cards (US)': 'House of Cards (2013)',
10 | 'Scandal (2012)': 'Scandal',
11 | 'Frontier (2016)': 'Frontier',
12 | 'American Dad!': 'American Dad'}
13 |
--------------------------------------------------------------------------------
/addon.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
12 |
13 | Get subtitles from Addic7ed.com
14 | Description for Addic7ed to come
15 |
16 | all
17 |
18 | GNU GENERAL PUBLIC LICENSE. Version 2, June 1991
19 | http://forum.xbmc.org/showthread.php?tid=184854
20 |
21 |
22 | https://github.com/cflannagan/service.subtitles.addic7ed
23 |
24 |
25 |
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | 1.0.0
2 | New release for XBMC 13.0 Gotham.
3 |
4 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Amelandbor/service.subtitles.addic7ed/ed7e9cf8091ddfa36750bb766c4baac5d9ab44f7/icon.png
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Amelandbor/service.subtitles.addic7ed/ed7e9cf8091ddfa36750bb766c4baac5d9ab44f7/logo.png
--------------------------------------------------------------------------------
/resources/language/English/strings.po:
--------------------------------------------------------------------------------
1 | # XBMC Media Center language file
2 | # Addon Name: Addic7ed.com subtitle service
3 | # Addon id: service.subtitles.addic7ed
4 | # Addon Provider: CFlannagan
5 | msgid ""
6 | msgstr ""
7 | "Project-Id-Version: XBMC Addons\n"
8 | "Report-Msgid-Bugs-To: \n"
9 | "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
10 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11 | "Last-Translator: XBMC Translation Team\n"
12 | "Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n"
13 | "MIME-Version: 1.0\n"
14 | "Content-Type: text/plain; charset=UTF-8\n"
15 | "Content-Transfer-Encoding: 8bit\n"
16 | "Language: en\n"
17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18 |
19 | msgctxt "#32001"
20 | msgid "(%d files)"
21 | msgstr ""
22 |
23 | msgctxt "#32002"
24 | msgid "Could not find matching episode in subtitle pack"
25 | msgstr ""
26 |
27 | msgctxt "#32003"
28 | msgid "Download didn't contain a subtitle file"
29 | msgstr ""
30 |
31 | msgctxt "#24000"
32 | msgid "Manual Search is not enabled currently"
33 | msgstr ""
34 |
--------------------------------------------------------------------------------
/resources/lib/Addic7edUtilities.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Based on contents from https://github.com/Diecke/service.subtitles.addicted
3 | # Thanks Diecke!
4 |
5 | import xbmc
6 |
7 | LANGUAGES = (
8 | ("Albanian", "29", "sq", "alb", "0", 30201),
9 | ("Arabic", "12", "ar", "ara", "1", 30202),
10 | ("Belarusian", "0", "hy", "arm", "2", 30203),
11 | ("Bosnian", "10", "bs", "bos", "3", 30204),
12 | ("Bulgarian", "33", "bg", "bul", "4", 30205),
13 | ("Catalan", "53", "ca", "cat", "5", 30206),
14 | ("Chinese", "17", "zh", "chi", "6", 30207),
15 | ("Croatian", "38", "hr", "hrv", "7", 30208),
16 | ("Czech", "7", "cs", "cze", "8", 30209),
17 | ("Danish", "24", "da", "dan", "9", 30210),
18 | ("Dutch", "23", "nl", "dut", "10", 30211),
19 | ("English", "2", "en", "eng", "11", 30212),
20 | ("Estonian", "20", "et", "est", "12", 30213),
21 | ("Persian", "52", "fa", "per", "13", 30247),
22 | ("Finnish", "31", "fi", "fin", "14", 30214),
23 | ("French", "8", "fr", "fre", "15", 30215),
24 | ("German", "5", "de", "ger", "16", 30216),
25 | ("Greek", "16", "el", "ell", "17", 30217),
26 | ("Hebrew", "22", "he", "heb", "18", 30218),
27 | ("Hindi", "42", "hi", "hin", "19", 30219),
28 | ("Hungarian", "15", "hu", "hun", "20", 30220),
29 | ("Icelandic", "6", "is", "ice", "21", 30221),
30 | ("Indonesian", "0", "id", "ind", "22", 30222),
31 | ("Italian", "9", "it", "ita", "23", 30224),
32 | ("Japanese", "11", "ja", "jpn", "24", 30225),
33 | ("Korean", "4", "ko", "kor", "25", 30226),
34 | ("Latvian", "21", "lv", "lav", "26", 30227),
35 | ("Lithuanian", "0", "lt", "lit", "27", 30228),
36 | ("Macedonian", "35", "mk", "mac", "28", 30229),
37 | ("Malay", "0", "ms", "may", "29", 30248),
38 | ("Norwegian", "3", "no", "nor", "30", 30230),
39 | ("Polish", "26", "pl", "pol", "31", 30232),
40 | ("Portuguese", "32", "pt", "por", "32", 30233),
41 | ("PortugueseBrazil", "48", "pb", "pob", "33", 30234),
42 | ("Romanian", "13", "ro", "rum", "34", 30235),
43 | ("Russian", "27", "ru", "rus", "35", 30236),
44 | ("Serbian", "36", "sr", "scc", "36", 30237),
45 | ("Slovak", "37", "sk", "slo", "37", 30238),
46 | ("Slovenian", "1", "sl", "slv", "38", 30239),
47 | ("Spanish", "28", "es", "spa", "39", 30240),
48 | ("Swedish", "25", "sv", "swe", "40", 30242),
49 | ("Thai", "0", "th", "tha", "41", 30243),
50 | ("Turkish", "30", "tr", "tur", "42", 30244),
51 | ("Ukrainian", "46", "uk", "ukr", "43", 30245),
52 | ("Vietnamese", "51", "vi", "vie", "44", 30246),
53 | ("BosnianLatin", "10", "bs", "bos", "100", 30204),
54 | ("Farsi", "52", "fa", "per", "13", 30247),
55 | ("English (US)", "2", "en", "eng", "100", 30212),
56 | ("English (UK)", "2", "en", "eng", "100", 30212),
57 | ("Portuguese (Brazilian)", "48", "pt-br", "pob", "100", 30234),
58 | ("Portuguese (Brazil)", "48", "pb", "pob", "33", 30234),
59 | ("Portuguese-BR", "48", "pb", "pob", "33", 30234),
60 | ("Brazilian", "48", "pb", "pob", "33", 30234),
61 | ("Español (Latinoamérica)", "28", "es", "spa", "100", 30240),
62 | ("Español (España)", "28", "es", "spa", "100", 30240),
63 | ("Spanish (Latin America)", "28", "es", "spa", "100", 30240),
64 | ("Español", "28", "es", "spa", "100", 30240),
65 | ("SerbianLatin", "36", "sr", "scc", "100", 30237),
66 | ("Spanish (Spain)", "28", "es", "spa", "100", 30240),
67 | ("Chinese (Traditional)", "17", "zh", "chi", "100", 30207),
68 | ("Chinese (Simplified)", "17", "zh", "chi", "100", 30207))
69 |
70 |
71 | def log(module,msg):
72 | xbmc.log((u"### [%s] - %s" % (module, msg,)).encode('utf-8'), level=xbmc.LOGDEBUG)
73 |
74 | def get_language_info(language):
75 | for lang in LANGUAGES:
76 | if lang[0] == language:
77 | return {'name': lang[0], '2let': lang[2], '3let': lang[3]}
--------------------------------------------------------------------------------
/resources/lib/__init__.py:
--------------------------------------------------------------------------------
1 | # Dummy file to make this directory a package.
2 |
--------------------------------------------------------------------------------
/service.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Based on contents from https://github.com/Diecke/service.subtitles.addicted
3 | # Thanks Diecke!
4 |
5 | import os
6 | import sys
7 | import xbmc
8 | import urllib
9 | import urllib2
10 | import xbmcvfs
11 | import xbmcaddon
12 | import xbmcgui
13 | import xbmcplugin
14 | import shutil
15 | import unicodedata
16 | import re
17 | import socket
18 | import string
19 |
20 | from BeautifulSoup import BeautifulSoup
21 |
22 | __addon__ = xbmcaddon.Addon()
23 | __scriptid__ = __addon__.getAddonInfo('id')
24 | __scriptname__ = __addon__.getAddonInfo('name')
25 | __version__ = __addon__.getAddonInfo('version')
26 | __language__ = __addon__.getLocalizedString
27 |
28 | __cwd__ = xbmc.translatePath( __addon__.getAddonInfo('path') ).decode("utf-8")
29 | __profile__ = xbmc.translatePath( __addon__.getAddonInfo('profile') ).decode("utf-8")
30 | __resource__ = xbmc.translatePath( os.path.join( __cwd__, 'resources', 'lib' ) ).decode("utf-8")
31 | __temp__ = xbmc.translatePath( os.path.join( __profile__, 'temp', '') ).decode("utf-8")
32 |
33 | sys.path.append (__resource__)
34 |
35 | from Addic7edUtilities import log, get_language_info
36 |
37 | self_host = "http://www.addic7ed.com"
38 | self_release_pattern = re.compile("Version (.+), ([0-9]+).([0-9])+ MBs")
39 |
40 | req_headers = {
41 | 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13',
42 | 'Referer': 'http://www.addic7ed.com'}
43 |
44 | def get_url(url):
45 | request = urllib2.Request(url, headers=req_headers)
46 | opener = urllib2.build_opener()
47 | response = opener.open(request)
48 |
49 | contents = response.read()
50 | return contents
51 |
52 | def append_subtitle(item):
53 | listitem = xbmcgui.ListItem(label=item['lang']['name'],
54 | label2=item['filename'],
55 | iconImage=item['rating'],
56 | thumbnailImage=item['lang']['2let'])
57 |
58 | listitem.setProperty("sync", 'true' if item["sync"] else 'false')
59 | listitem.setProperty("hearing_imp", 'true' if item["hearing_imp"] else 'false')
60 |
61 | url = "plugin://%s/?action=download&link=%s&filename=%s" % (__scriptid__,
62 | item['link'],
63 | item['filename'])
64 | xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=listitem, isFolder=False)
65 |
66 | def query_TvShow(name, season, episode, langs, file_original_path):
67 | name = addic7ize(name).lower().replace(" ", "_")
68 | searchurl = "%s/serie/%s/%s/%s/addic7ed" %(self_host, name, season, episode)
69 | filename_string = "%s.S%.2dE%.2d" %(name.replace("_", ".").title(), int(season), int(episode) )
70 | query(searchurl, langs, file_original_path, filename_string)
71 |
72 | def query_Film(name, year, langs, file_original_path):
73 | name = urllib.quote(name.replace(" ", "_"))
74 | searchurl = "%s/film/%s_(%s)-Download" %(self_host,name, str(year))
75 | filename_string = "%s" %(name.replace("_", ".").title() )
76 | query(searchurl, langs, file_original_path, filename_string)
77 |
78 | def query(searchurl, langs, file_original_path, filename_string):
79 | sublinks = []
80 | socket.setdefaulttimeout(20)
81 | request = urllib2.Request(searchurl, headers=req_headers)
82 | request.add_header('Pragma', 'no-cache')
83 | page = urllib2.build_opener().open(request)
84 | content = page.read()
85 | content = content.replace("The safer, easier way", "The safer, easier way \" />")
86 | soup = BeautifulSoup(content)
87 |
88 | file_original_path_clean = normalizeString(file_original_path.encode('utf-8'))
89 | file_name = str(os.path.basename(file_original_path_clean)).split("-")[-1].lower()
90 |
91 | for langs_html in soup("td", {"class" : "language"}):
92 |
93 | try:
94 | subs = langs_html.findPrevious("td", {"class":"NewsTitle", "colspan" : "3"})
95 | fullLanguage = str(langs_html).split('class="language">')[1].split(' -1:
99 | hashed = True
100 | else:
101 | hashed = False
102 |
103 | try:
104 | lang = get_language_info(fullLanguage)
105 | except:
106 | lang = ""
107 |
108 | statusTD = langs_html.findNext("td")
109 | status = statusTD.find("b").string.strip()
110 |
111 | linkTD = statusTD.findNext("td")
112 | link = "%s%s" % (self_host,linkTD.find("a")["href"])
113 |
114 | if(subs.findNext("td", {"class":"newsDate", "colspan" : "2"}).findAll('img', {'title': 'Hearing Impaired'})):
115 | HI = True
116 | else:
117 | HI = False
118 |
119 | if status == "Completed" and (lang['3let'] in langs) :
120 | sublinks.append({'rating': '0', 'filename': "%s-%s" %(filename_string, subteams ), 'sync': hashed, 'link': link, 'lang': lang, 'hearing_imp': HI})
121 | except:
122 | log(__name__, "ERROR IN BS")
123 | pass
124 |
125 | sublinks.sort(key=lambda x: [not x['sync']])
126 | log(__name__, "sub='%s'" % (sublinks))
127 |
128 | for s in sublinks:
129 | append_subtitle(s)
130 |
131 | def search_manual(searchstr, languages, filename):
132 | xbmc.executebuiltin((u'Notification(%s,%s)' % (__scriptname__ , __language__(24000))).encode('utf-8'))
133 | return False
134 | search_string = prepare_search_string(searchstr)
135 | url = self_host + "/search.php?search=" + search_string + '&Submit=Search'
136 | content, response_url = geturl(url)
137 |
138 | if content is not None:
139 | return False
140 | # getallsubs(content, languages, filename)
141 |
142 | def search_filename(filename, languages):
143 | title, year = xbmc.getCleanMovieTitle(filename)
144 | log(__name__, "clean title: \"%s\" (%s)" % (title, year))
145 | try:
146 | yearval = int(year)
147 | except ValueError:
148 | yearval = 0
149 | if title and yearval > 1900:
150 | query_Film(title, year, item['3let_language'], filename)
151 | else:
152 | match = re.search(r'\WS(?P\d\d)E(?P\d\d)', title, flags=re.IGNORECASE)
153 | if match is not None:
154 | tvshow = string.strip(title[:match.start('season')-1])
155 | season = string.lstrip(match.group('season'), '0')
156 | episode = string.lstrip(match.group('episode'), '0')
157 | query_TvShow(tvshow, season, episode, item['3let_language'], filename)
158 | else:
159 | search_manual(filename, item['3let_language'], filename)
160 |
161 |
162 | def Search(item):
163 | filename = os.path.splitext(os.path.basename(item['file_original_path']))[0]
164 | log(__name__, "Search_addic7ed='%s', filename='%s', addon_version=%s" % (item, filename, __version__))
165 |
166 | if item['mansearch']:
167 | search_manual(item['mansearchstr'], item['3let_language'], filename)
168 | elif item['tvshow']:
169 | query_TvShow(item['tvshow'], item['season'], item['episode'], item['3let_language'], filename)
170 | elif item['title'] and item['year']:
171 | query_Film(item['title'], item['year'], item['3let_language'], filename)
172 | else:
173 | search_filename(filename, item['3let_language'])
174 |
175 |
176 | def download(link):
177 | subtitle_list = []
178 |
179 | if xbmcvfs.exists(__temp__):
180 | shutil.rmtree(__temp__)
181 | xbmcvfs.mkdirs(__temp__)
182 |
183 | file = os.path.join(__temp__, "addic7ed.srt")
184 |
185 | f = get_url(link)
186 |
187 | local_file_handle = open(file, "wb")
188 | local_file_handle.write(f)
189 | local_file_handle.close()
190 |
191 | subtitle_list.append(file)
192 |
193 | if len(subtitle_list) == 0:
194 | if search_string:
195 | xbmc.executebuiltin((u'Notification(%s,%s)' % (__scriptname__ , __language__(32002))).encode('utf-8'))
196 | else:
197 | xbmc.executebuiltin((u'Notification(%s,%s)' % (__scriptname__ , __language__(32003))).encode('utf-8'))
198 |
199 | return subtitle_list
200 |
201 |
202 | def normalizeString(str):
203 | return unicodedata.normalize(
204 | 'NFKD', unicode(unicode(str, 'utf-8'))
205 | ).encode('ascii', 'ignore')
206 |
207 | # Sometimes search fail because Addic7ed uses URLs that does not match the TheTVDB format.
208 | # This will probably grow to be a hardcoded colleciton over time.
209 | def addic7ize(str):
210 |
211 | addic7ize_dict = eval(open(__cwd__ + '/addic7ed_dict.txt').read())
212 |
213 | return addic7ize_dict.get(str, str)
214 |
215 |
216 | def get_params():
217 | param = {}
218 | paramstring = sys.argv[2]
219 | if len(paramstring) >= 2:
220 | params = paramstring
221 | cleanedparams = params.replace('?', '')
222 | if (params[len(params) - 1] == '/'):
223 | params = params[0:len(params) - 2]
224 | pairsofparams = cleanedparams.split('&')
225 | param = {}
226 | for i in range(len(pairsofparams)):
227 | splitparams = pairsofparams[i].split('=')
228 | if (len(splitparams)) == 2:
229 | param[splitparams[0]] = splitparams[1]
230 |
231 | return param
232 |
233 | params = get_params()
234 |
235 | if params['action'] == 'search' or params['action'] == 'manualsearch':
236 | item = {}
237 | item['temp'] = False
238 | item['rar'] = False
239 | item['mansearch'] = False
240 | item['year'] = xbmc.getInfoLabel("VideoPlayer.Year") # Year
241 | item['season'] = str(xbmc.getInfoLabel("VideoPlayer.Season")) # Season
242 | item['episode'] = str(xbmc.getInfoLabel("VideoPlayer.Episode")) # Episode
243 | item['tvshow'] = normalizeString(xbmc.getInfoLabel("VideoPlayer.TVshowtitle")) # Show
244 | item['title'] = normalizeString(xbmc.getInfoLabel("VideoPlayer.OriginalTitle")) # try to get original title
245 | item['file_original_path'] = urllib.unquote(xbmc.Player().getPlayingFile().decode('utf-8')) # Full path
246 | item['3let_language'] = []
247 |
248 | if 'searchstring' in params:
249 | item['mansearch'] = True
250 | item['mansearchstr'] = params['searchstring']
251 |
252 | for lang in urllib.unquote(params['languages']).decode('utf-8').split(","):
253 | item['3let_language'].append(xbmc.convertLanguage(lang, xbmc.ISO_639_2))
254 |
255 | if item['title'] == "":
256 | item['title'] = normalizeString(xbmc.getInfoLabel("VideoPlayer.Title")) # no original title, get just Title
257 |
258 | if item['episode'].lower().find("s") > -1: # Check if season is "Special"
259 | item['season'] = "0" #
260 | item['episode'] = item['episode'][-1:]
261 |
262 | if item['file_original_path'].find("http") > -1:
263 | item['temp'] = True
264 |
265 | elif item['file_original_path'].find("rar://") > -1:
266 | item['rar'] = True
267 | item['file_original_path'] = os.path.dirname(item['file_original_path'][6:])
268 |
269 | elif item['file_original_path'].find("stack://") > -1:
270 | stackPath = item['file_original_path'].split(" , ")
271 | item['file_original_path'] = stackPath[0][8:]
272 |
273 | Search(item)
274 |
275 | elif params['action'] == 'download':
276 | subs = download(params["link"])
277 | for sub in subs:
278 | listitem = xbmcgui.ListItem(label=sub)
279 | xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=sub, listitem=listitem, isFolder=False)
280 |
281 | xbmcplugin.endOfDirectory(int(sys.argv[1])) # send end of directory to XBMC
282 |
--------------------------------------------------------------------------------