Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy support #325

Merged
merged 30 commits into from
Mar 9, 2024
Merged

Proxy support #325

merged 30 commits into from
Mar 9, 2024

Conversation

nikolaev-rd
Copy link
Contributor

@nikolaev-rd nikolaev-rd commented Feb 3, 2024

Добавлена поддержка прокси для запросов плагина к API Kino.pub

Не дождавшись ответа/реакции на тикет #318, решил реализовать поддержку прокси самостоятельно.
Resolves #318

Как это работает

Плагин использует системные настройки прокси, которые задаются через меню: System → Internet Access

image

Плагин проверяет, что системная настройка "Use proxy server" включена, далее распознает указанный тип прокси, и устанавливает этот прокси для всех запросов к API.

Для получения системных настроек написан отдельный класс — работает через JSONRPC API через метод Settings.GetSettingValue

Что умеет

Теперь плагин поддерживает прокси всех типов (с авторизацией и без):

  • HTTP
  • HTTPS
  • SOCKS4
  • SOCKS5

Проверка

Протестировано на прокси HTTP (без авторизации) и SOCKS5 (с авторизацией).

@nikolaev-rd
Copy link
Contributor Author

На новом устройстве обнаружил еще место, где надо тоже добавить поддержку прокси (auth.py):

2024-02-04 21:07:11.955 T:906     error <general>: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
                                                    - NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
                                                   Error Type: <class 'urllib.error.URLError'>
                                                   Error Contents: <urlopen error [Errno 104] Connection reset by peer>
                                                   Traceback (most recent call last):
                                                     File "/usr/lib/python3.11/urllib/request.py", line 1348, in do_open
                                                     File "/usr/lib/python3.11/http/client.py", line 1282, in request
                                                     File "/usr/lib/python3.11/http/client.py", line 1328, in _send_request
                                                     File "/usr/lib/python3.11/http/client.py", line 1277, in endheaders
                                                     File "/usr/lib/python3.11/http/client.py", line 1037, in _send_output
                                                     File "/usr/lib/python3.11/http/client.py", line 975, in send
                                                     File "/usr/lib/python3.11/http/client.py", line 1454, in connect
                                                     File "/usr/lib/python3.11/ssl.py", line 517, in wrap_socket
                                                     File "/usr/lib/python3.11/ssl.py", line 1075, in _create
                                                     File "/usr/lib/python3.11/ssl.py", line 1346, in do_handshake
                                                   ConnectionResetError: [Errno 104] Connection reset by peer

                                                   During handling of the above exception, another exception occurred:

                                                   Traceback (most recent call last):
                                                     File "/storage/.kodi/addons/video.kino.pub/addon.py", line 6, in <module>
                                                       plugin.run()
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/plugin.py", line 88, in run
                                                       self.routing.dispatch(self.path)
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/routing.py", line 71, in dispatch
                                                       view_func(**kwargs)
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/main.py", line 86, in login
                                                       plugin.auth.get_token()
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/auth.py", line 218, in get_token
                                                       self._activate()
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/auth.py", line 204, in _activate
                                                       resp = self._get_device_code()
                                                              ^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/auth.py", line 127, in _get_device_code
                                                       resp = self._make_request(payload)
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/storage/.kodi/addons/video.kino.pub/resources/lib/auth.py", line 85, in _make_request
                                                       response = urllib.request.urlopen(
                                                                  ^^^^^^^^^^^^^^^^^^^^^^^
                                                     File "/usr/lib/python3.11/urllib/request.py", line 216, in urlopen
                                                     File "/usr/lib/python3.11/urllib/request.py", line 519, in open
                                                     File "/usr/lib/python3.11/urllib/request.py", line 536, in _open
                                                     File "/usr/lib/python3.11/urllib/request.py", line 496, in _call_chain
                                                     File "/usr/lib/python3.11/urllib/request.py", line 1391, in https_open
                                                     File "/usr/lib/python3.11/urllib/request.py", line 1351, in do_open
                                                   urllib.error.URLError: <urlopen error [Errno 104] Connection reset by peer>
                                                   -->End of Python script error report<--

@nikolaev-rd nikolaev-rd changed the title Proxy Support [Draft] Proxy Support Feb 5, 2024
requirements_dev.in Outdated Show resolved Hide resolved
src/resources/lib/xbmc_settings.py Outdated Show resolved Hide resolved
src/resources/lib/xbmc_settings.py Show resolved Hide resolved
src/resources/lib/xbmc_settings.py Outdated Show resolved Hide resolved
src/resources/lib/xbmc_settings.py Outdated Show resolved Hide resolved
src/resources/lib/xbmc_settings.py Outdated Show resolved Hide resolved
@quarckster
Copy link
Owner

Спасибо за PR ❤️

@quarckster
Copy link
Owner

Ещё нужно разобраться с тестами, ни один не проходит.

@nikolaev-rd
Copy link
Contributor Author

Ещё нужно разобраться с тестами, ни один не проходит.

Я вот даже не знаю, че с этими тестами. Это точно я сломал?
Error: no pod with name or ID kodipod found: no such pod

@nikolaev-rd
Copy link
Contributor Author

На новом устройстве обнаружил еще место, где надо тоже добавить поддержку прокси (auth.py):

@quarckster смотрю как попроще сюда тоже добавить поддержку прокси, потому что иначе нельзя сделать активацию устройства, и ощущение что можно унаследовать KinoPubClient + подпилить потом часть методов в классе Auth.
Иначе придется копипастить код для прокси, или выносить его еще куда-нить, чтобы потом в двух местах использовать.

Что скажешь?

@nikolaev-rd
Copy link
Contributor Author

Ещё нужно разобраться с тестами, ни один не проходит.

Я вот даже не знаю, че с этими тестами. Это точно я сломал? Error: no pod with name or ID kodipod found: no such pod

С тестами всё нормально, вот недавний PR, в котором тесты прошли #323

Все логи забиты этой ошибкой:

2024-02-10 21:49:24.449 T:98      ERROR <general>: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
                                                    - NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
                                                   Error Type: <class 'ModuleNotFoundError'>
                                                   Error Contents: No module named 'socks'
                                                   Traceback (most recent call last):
                                                     File "/home/kodi/.kodi/addons/video.kino.pub/addon.py", line 2, in <module>
                                                       from resources.lib.main import plugin
                                                     File "/home/kodi/.kodi/addons/video.kino.pub/resources/lib/main.py", line 17, in <module>
                                                       from resources.lib.plugin import Plugin
                                                     File "/home/kodi/.kodi/addons/video.kino.pub/resources/lib/plugin.py", line 18, in <module>
                                                       from resources.lib.client import KinoPubClient
                                                     File "/home/kodi/.kodi/addons/video.kino.pub/resources/lib/client.py", line 17, in <module>
                                                       import socks
                                                   ModuleNotFoundError: No module named 'socks'
                                                   -->End of Python script error report<--

@quarckster подскажи, где мне еще надо прописать этот модуль?

@quarckster
Copy link
Owner

quarckster commented Feb 20, 2024

@quarckster подскажи, где мне еще надо прописать этот модуль?

Необходимо сюда https://github.com/quarckster/kodi.kino.pub/tree/master/tests/data/addons положить этот плагин https://kodi.tv/addons/nexus/script.module.pysocks/

@nikolaev-rd
Copy link
Contributor Author

Положил, но ошибка та же:

                                                     File "/home/kodi/.kodi/addons/video.kino.pub/resources/lib/client.py", line 17, in <module>
                                                       import socks
                                                   ModuleNotFoundError: No module named 'socks'
                                                   -->End of Python script error report<--

@amironofff
Copy link

У меня проблема, как в тикете 318. Поддержка кинопаба (очень добрые люди) отправила сюда. Я почитал эти тикеты, и как в меме "ничего не понял, но очень интересно". Есть где-нибудь инструкция как починить? Или нужно искать где-то прокси и просто прописывать его в настройках Kodi?

@quarckster
Copy link
Owner

У меня проблема, как в тикете 318. Поддержка кинопаба (очень добрые люди) отправила сюда. Я почитал эти тикеты, и как в меме "ничего не понял, но очень интересно". Есть где-нибудь инструкция как починить? Или нужно искать где-то прокси и просто прописывать его в настройках Kodi?

Поддержка прокси ещё не реализована. Постараюсь помочь с этим пулл реквестом.

@amironofff
Copy link

У меня проблема, как в тикете 318. Поддержка кинопаба (очень добрые люди) отправила сюда. Я почитал эти тикеты, и как в меме "ничего не понял, но очень интересно". Есть где-нибудь инструкция как починить? Или нужно искать где-то прокси и просто прописывать его в настройках Kodi?

Поддержка прокси ещё не реализована. Постараюсь помочь с этим пулл реквестом.

Спасибо огромное! Очень жду! Совсем недавно нашел как победить фризы через InputStream. И тут эта проблема. Спасибо заранее еще раз!

@nikolaev-rd
Copy link
Contributor Author

@quarckster похоже тесты не проходят по коммитам от меня, а по твоим коммитам работают. Видимо чето с правами.

@quarckster
Copy link
Owner

quarckster commented Feb 24, 2024

@quarckster похоже тесты не проходят по коммитам от меня, а по твоим коммитам работают. Видимо чето с правами.

Там надо было подправить БД аддонов Kodi Addons33.db, я добавил pysocks, и тесты стали проходить.

Copy link
Contributor Author

@nikolaev-rd nikolaev-rd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

@quarckster
Copy link
Owner

Я ещё потетсирую изменения у себя и хотел бы добавить тесты.

@nikolaev-rd
Copy link
Contributor Author

Я ещё потетсирую изменения у себя и хотел бы добавить тесты.

На RPi2 и прокси через http (без авторизации) / socks (с авторизацией) я проверил — работает.

@amironofff
Copy link

У меня не заработало на SOCK4.
Вот кусок лога - на сертификаты ругается:
2024-02-25 16:29:52.085 T:734 error : EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'urllib.error.URLError'>
Error Contents: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)>
Traceback (most recent call last):
File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
h.request(req.get_method(), req.selector, req.data, headers,
File "/usr/lib/python3.9/http/client.py", line 1255, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1301, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
self.send(msg)
File "/usr/lib/python3.9/http/client.py", line 950, in send
self.connect()
File "/usr/lib/python3.9/http/client.py", line 1424, in connect
self.sock = self._context.wrap_socket(self.sock,
File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.9/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)

                                               During handling of the above exception, another exception occurred:
                                               
                                               Traceback (most recent call last):
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/addon.py", line 6, in <module>
                                                   plugin.run()
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/plugin.py", line 90, in run
                                                   self.routing.dispatch(self.path)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/routing.py", line 71, in dispatch
                                                   view_func(**kwargs)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/main.py", line 151, in items
                                                   response = plugin.items.get(f"items/{heading}", data=data, exclude_anime=exclude_anime)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/modeling.py", line 42, in get
                                                   resp = self.plugin.client(endpoint).get(data=data)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/client.py", line 214, in get
                                                   return self._make_request(request)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/client.py", line 203, in _make_request
                                                   response = self.opener.open(request, timeout=TIMEOUT)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 517, in open
                                                   response = self._open(req, data)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
                                                   result = self._call_chain(self.handle_open, protocol, protocol +
                                                 File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
                                                   result = func(*args)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
                                                   return self.do_open(http.client.HTTPSConnection, req,
                                                 File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
                                                   raise URLError(err)
                                               urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)>
                                               -->End of Python script error report<--

2024-02-25 16:29:52.202 T:733 error : GetDirectory - Error getting plugin://video.kino.pub/items/all/fresh/
2024-02-25 16:29:52.218 T:559 error : CGUIMediaWindow::GetDirectory(plugin://video.kino.pub/items/all/fresh/) failed

@nikolaev-rd
Copy link
Contributor Author

nikolaev-rd commented Feb 25, 2024

У меня не заработало на SOCK4. Вот кусок лога - на сертификаты ругается

Тут что-то с прокси — используется самоподписной сертификат, что все либы считают неправильным (я тут с ними согласен). Вот такой попробуй (чисто для теста, это рандомная прокся из интернетов): 103.148.57.103:30001 (SOCKS4)

@amironofff
Copy link

Попробовал с предложенным прокси - результат такой же, но есть отличие визуальное: после нажатие на кнопку "Закладки" ожидание сильно дольше до появления ошибки.
В логах опять ругается на сертификат:
_2024-02-25 23:14:34.241 T:745 error : GetDirectory - Error getting plugin://video.kino.pub/bookmarks/
2024-02-25 23:14:34.250 T:546 error : CGUIMediaWindow::GetDirectory(plugin://video.kino.pub/bookmarks/) failed
2024-02-25 23:15:07.436 T:546 error : Control 55 in window 10025 has been asked to focus, but it can't
2024-02-25 23:15:49.925 T:793 error : EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'urllib.error.URLError'>
Error Contents: <urlopen error [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)>
Traceback (most recent call last):
File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
h.request(req.get_method(), req.selector, req.data, headers,
File "/usr/lib/python3.9/http/client.py", line 1255, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1301, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1250, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.9/http/client.py", line 1010, in _send_output
self.send(msg)
File "/usr/lib/python3.9/http/client.py", line 950, in send
self.connect()
File "/usr/lib/python3.9/http/client.py", line 1424, in connect
self.sock = self._context.wrap_socket(self.sock,
File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.9/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)

                                               During handling of the above exception, another exception occurred:
                                               
                                               Traceback (most recent call last):
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/addon.py", line 6, in <module>
                                                   plugin.run()
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/plugin.py", line 90, in run
                                                   self.routing.dispatch(self.path)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/routing.py", line 71, in dispatch
                                                   view_func(**kwargs)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/main.py", line 319, in bookmarks
                                                   response = plugin.client("bookmarks").get()
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/client.py", line 214, in get
                                                   return self._make_request(request)
                                                 File "/home/osmc/.kodi/addons/video.kino.pub/resources/lib/client.py", line 203, in _make_request
                                                   response = self.opener.open(request, timeout=TIMEOUT)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 517, in open
                                                   response = self._open(req, data)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
                                                   result = self._call_chain(self.handle_open, protocol, protocol +
                                                 File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
                                                   result = func(*args)
                                                 File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
                                                   return self.do_open(http.client.HTTPSConnection, req,
                                                 File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
                                                   raise URLError(err)
                                               urllib.error.URLError: <urlopen error [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)>
                                               -->End of Python script error report<--_

И еще интересный момент - после проверки предложенного хоста с портом на все типы прокси, которые есть в Kodi, я выключил прокси и о чудо - все заработало. Проверил на "Закладки" - там провалился в папку и запустил фильм, и на "New", оттуда тоже фильм запустился.

@nikolaev-rd
Copy link
Contributor Author

Попробовал с предложенным прокси - результат такой же, но есть отличие визуальное: после нажатие на кнопку "Закладки" ожидание сильно дольше до появления ошибки.

Странно, у меня работает (со второго раза запрос прошел, прокся эта рандомная — явно медленная, но всё же). В настройках так делал:

Type: SOCKS4A
Host: 103.148.57.103
Port: 30001

Опять же, советую купить где-нить прокси/vpn, чтобы не страдать с рандомными прокси из интернетов, где непонятно что на них с трафиком происходит потом.

Ошибка

urllib.error.URLError: <urlopen error [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1123)>

возникает в случаях, когда к http-прокси пытаются обращаться как к https-прокси (на самом деле там должен быть http + TLS), похоже тут всё тоже верно.

@quarckster quarckster changed the title [Draft] Proxy Support Proxy support Mar 9, 2024
@quarckster quarckster merged commit d451b52 into quarckster:master Mar 9, 2024
4 checks passed
@nikolaev-rd nikolaev-rd deleted the proxy branch March 9, 2024 17:26
@abdullasharapov
Copy link

abdullasharapov commented Mar 27, 2024

Подскажите по деталям. Все запросы к API теперь заворачиваются через прокси. А как дело обстоит с контентом? Контент тянется с другого адреса?
Ну и в целом, использование прокси на системном уровне коди вероятно повлияет на то, что остальные приложения будут гонять трафик через проксю. Не рассматриваете возможность использования прокси лишь на уровне аддона, т.е. добавить соответствующий пункт в меню аддона?

@nikolaev-rd
Copy link
Contributor Author

Подскажите по деталям. Все запросы к API теперь заворачиваются через прокси. А как дело обстоит с контентом? Контент тянется с другого адреса?

Да, видео/картинки стримятся напрямую, через прокси идут только запросы к API Кинопаба.

Ну и в целом, использование прокси на системном уровне коди вероятно повлияет на то, что остальные приложения будут гонять трафик через проксю.

Такое возможно, но из моей практики — редко какой аддон умеет подхватывать системную прокси.

Не рассматриваете возможность использования прокси лишь на уровне аддона, т.е. добавить соответствующий пункт в меню аддона?

По идеи можно сделать, но мне показалось что системные настройки уже есть, наоборот так проще — настроил в одном месте, а не в каждом плагине каждый раз. К тому же в тех плагинах, которые умеют в системную прокси, как правило в настройках плагина можно вкл/выкл использование прокси, либо указать свою прокси в плагине.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Connection reset by peer
4 participants