Задать вопрос
  • Как сделать скачивание файла с github релиза на python?

    @eminsk
    developer python, javascripts
    Проблема в том, что GitHub автоматически перенаправляет запросы к файлам в релизах, а библиотека requests по умолчанию не следует перенаправлениям при использовании stream=True. Также GitHub требует правильные заголовки для скачивания файлов.

    Данный код корректно все нормально делает без ошибок и скачивает в папку где запущен мой скрипт.
    если папка download нету она создается автоматически.
    А также сделал со всеми проверками в коде
    Установи не забудь только requests
    import os
    import requests
    from urllib.parse import urlparse
    
    def versionDownload(url, folder, chunk_size=8192):
        if not os.path.exists(folder):
            os.makedirs(folder, exist_ok=True)
        
        if "github.com" in url and "/releases/" in url and "/download/" not in url:
            print("Обнаружена ссылка на страницу релиза. Попытка найти правильную ссылку...")
            page_response = requests.get(url)
            page_response.raise_for_status()
            
            import re
            download_links = re.findall(r'href="([^"]*\/download\/[^"]*)"', page_response.text)
            
            if download_links:
                url = "https://github.com" + download_links[0] if download_links[0].startswith('/') else download_links[0]
                print(f"Найдена ссылка для скачивания: {url}")
            else:
                print("Не удалось найти файлы для скачивания на странице релиза")
                return None
        
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'application/octet-stream'
        }
        
        print(f"Начался процесс скачивания с URL: {url}")
        
        with requests.get(url, headers=headers, stream=True, allow_redirects=True) as r:
            r.raise_for_status()
            
            content_type = r.headers.get('Content-Type', '')
            if 'text/html' in content_type:
                print("Ошибка: получен HTML вместо файла!")
                print(f"Content-Type: {content_type}")
                print("Проверьте правильность URL")
                return None
            
            filename = "engine.zip"
            if 'Content-Disposition' in r.headers:
                content_disp = r.headers['Content-Disposition']
                if 'filename=' in content_disp:
                    filename = content_disp.split('filename=')[1].strip('"')
            else:
                parsed_url = urlparse(url)
                if parsed_url.path:
                    filename = os.path.basename(parsed_url.path) or "engine.zip"
            
            file_path = os.path.join(folder, filename)
            
            total_size = int(r.headers.get('Content-Length', 0))
            downloaded_size = 0
            
            print(f"Скачивание {filename}...")
            if total_size > 0:
                print(f"Размер файла: {total_size / (1024*1024):.2f} MB")
            
            with open(file_path, 'wb') as f:
                for chunk in r.iter_content(chunk_size=chunk_size):
                    if chunk:
                        f.write(chunk)
                        downloaded_size += len(chunk)
                        
                        if total_size > 0:
                            progress = (downloaded_size / total_size) * 100
                            print(f"\rПрогресс: {progress:.1f}% ({downloaded_size / (1024*1024):.2f} MB)", end='', flush=True)
            
            print(f"\nФайл успешно скачан: {file_path}")
            return file_path
    
    if __name__ == "__main__":
        url = "https://github.com/artyom7774/Game-Engine-3/releases/download/GE3.12.0/Game-Engine-3-windows.sfx.exe"
        versionDownload(url, "./downloads")
    Ответ написан
    Комментировать
  • При установке Bootstrap на Laravel ошибка, как решить?

    @eminsk
    developer python, javascripts
    Эта ошибка ENOSPC: System limit for number of file watchers reached возникает из-за того, что система наблюдения за файлами достигла лимита. На shared-хостинге это частая проблема:

    Отключить watch режим
    npm run build
    или
    npm run production
    Это скомпилирует ассеты один раз без постоянного отслеживания изменений.

    Настроить webpack.mix.js
    В файле webpack.mix.js добавь опцию для отключения polling:
    const mix = require('laravel-mix');
    
    mix.js('resources/js/app.js', 'public/js')
       .sass('resources/sass/app.scss', 'public/css')
       .options({
           processCssUrls: false
       });
    
    // Отключить file watching для production
    if (mix.inProduction()) {
        mix.version();
    }


    Использовать polling вместо inotify
    Создай файл .env.local в корне проекта:
    CHOKIDAR_USEPOLLING=true
    CHOKIDAR_INTERVAL=1000

    Локальная разработка
    Рекомендую:
    Разрабатывать локально с npm run dev
    На хостинге использовать только npm run build
    Загружать уже скомпилированные файлы из папки public/
    Альтернативный подход
    Если нужно часто пересобирать ассеты на хостинге:
    npm run watch-poll
    Оптимизация для хостинга
    В package.json добавь скрипт:
    {
      "scripts": {
        "build-prod": "npm run production && npm run build"
      }
    }


    И последний вариант найди самый дешевый VPS уже в год (примерно 10-12$) можно купить по цене хостинга:
    и там уже настрой сам как надо, согласно документации уже.
    На котором не каких ограничений у тебя не каких уже не будет.
    Ответ написан
  • Как в react-chartjs-2 задать отступ между круговой диаграммой и лейблами?

    @eminsk
    developer python, javascripts
    Самый простой способ - использовать layout.padding с динамическим вычислением отступов на основе количества и длины лейблов.
    const calculatePadding = (labels) => {
        const labelCount = labels.length;
        const maxLabelLength = Math.max(...labels.map(label => label.length));
        
        return {
            left: 40,
            right: Math.max(100, labelCount * 20 + maxLabelLength * 3)
        };
    };


    Более гибкое решение - отключить встроенную легенду и создать собственную
    <div className="pie-chart-grid-container">
        <div className="pie-chart-canvas">
            <Pie data={data} options={optionsWithoutLegend} />
        </div>
        <div className="custom-legend">
            {/* Кастомная легенда */}
        </div>
    </div>


    Убери фиксированные margin-left: 11% и используй flexbox или grid для центрирования:
    .pie-chart-wrapper {
        width: 100%;
        height: 100%;
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
    }


    Для мобильных устройств рекомендую размещать легенду снизу диаграммы вместо справа.
    Ответ написан
    Комментировать
  • Как изменить родительский альфа-канал в canvas Tkinter python?

    @eminsk
    developer python, javascripts
    from tkinter import Canvas,Tk,Button,PhotoImage, Toplevel
    
    root = Tk()
    root.wm_attributes('-alpha', 0.5)
    root.wm_attributes("-topmost", True)
    root.overrideredirect(True) 
    img = PhotoImage(file=r"pics\image_19x19.png")
    canvas = Canvas(root, width=1920, height=1080, highlightthickness=0)
    canvas.pack()
    
    image_window = Toplevel(root)
    image_window.overrideredirect(True) 
    image_window.wm_attributes("-topmost", True) 
    
    image_canvas = Canvas(image_window, width=img.width(), height=img.height(), highlightthickness=0)
    image_canvas.pack()
    
    image_window.withdraw()
    
    def leftclick(event):
        x = event.x_root
        y = event.y_root
    
        image_canvas.delete("all")
        image_canvas.create_image(img.width() // 2, img.height() // 2, image=img)
    
        image_window.geometry(f"+{x}+{y}")
        image_window.deiconify()
    
    root.bind('<Button-1>' , leftclick)
    root.mainloop()
    Ответ написан
    Комментировать
  • (customtkinter) Как передать значение элемента из одного файла в другой?

    @eminsk
    developer python, javascripts
    В следующем коде 3 файла мои и все нормально работает.
    когда чек бокс выбран будет 1 а когда чек бокс не выбран то будет 0
    сохрани все эти файлы рядом по именам чтобы все файлы были рядом и формате UTF-8

    # main.py
    import customtkinter as ctk
    from right_menu import RightMenu
    from bottom_menu import BottomMenu
    
    def main():
        root = ctk.CTk()
        root.geometry("600x400")
        root.title("Demo передачи значения между меню")
        right = RightMenu(root)
        right.pack(side="right", fill="y")
        bottom = BottomMenu(root, right_menu=right)
        bottom.pack(side="bottom", fill="x")
    
        root.mainloop()
    
    if __name__ == "__main__":
        main()


    # right_menu.py
    import customtkinter as ctk
    class RightMenu(ctk.CTkFrame):
        def __init__(self, master, **kwargs):
            super().__init__(master, **kwargs)
            self.right_menu = ctk.CTkFrame(self,
                                           width=200,
                                           corner_radius=0,
                                           border_color="#242323",
                                           border_width=1)
            self.right_menu.pack(side="right", fill="y")
            self.checkbox = ctk.CTkCheckBox(
                self.right_menu,
                text="Contrast",
                width=100,
                height=25,
                command=self.toggle_slider
            )
            self.checkbox.pack(padx=10, pady=10, anchor="w")
    
        def toggle_slider(self):
            print("Checkbox toggled, now:", self.checkbox.get())
    
        def get_effects(self):
            """
            Возвращает текущее состояние чекбокса:
            1 — включён; 0 — выключен.
            """
            return self.checkbox.get()


    # bottom_menu.py
    import customtkinter as ctk
    class BottomMenu(ctk.CTkFrame):
        def __init__(self, master, right_menu, **kwargs):
            super().__init__(master, corner_radius=0, height=100,
                             border_color="#242323", border_width=1, **kwargs)
            self.right_menu = right_menu
            apply_btn = ctk.CTkButton(
                self,
                text="Применить",
                command=self.on_apply_changes_click
            )
            apply_btn.pack(padx=10, pady=10, anchor="e")
    
        def on_apply_changes_click(self):
            checkbox_value = self.right_menu.get_effects()
            print(f"Текущее состояние чекбокса Contrast: {checkbox_value}")
    Ответ написан
    Комментировать
  • Как исправить отображение в игре?

    @eminsk
    developer python, javascripts
    Тебе в функции painting после строки current_rad = float(new_rad)

    нужно добавить дополнительную проверку:
    if current_rad >= 190:
                radius_mult = 2.0
            else:
                radius_mult = 1.0
    Ответ написан
    Комментировать
  • Как обратится к значению proxy(object)?

    @eminsk
    developer python, javascripts
    Проблема в том, что filter() возвращает массив объектов, даже если найден только один элемент. В твоем случае test - это массив с одним объектом Proxy(Object), а не сам объект.
    Чтобы получить доступ к свойству hours, тебе нужно обратиться к первому (и единственному) элементу массива:
    const test = this.ArrBookingHours.filter((hour) => hour.date === day.toDateString())
    console.log(test)
    console.log(test[0].hours)

    строка console.log(test[0].hours) - это обращение к первому элементу массива

    Еще есть компактнее с использованием find и опциональной цепочки:
    const booking = this.ArrBookingHours.find(
      hour => hour.date === day.toDateString()
    )
    
    console.log(booking?.hours ?? 'Нет записи на эту дату')


    Используя этот способ - можно избежать ошибки Cannot read property 'hours' of undefined, если нет ни одного совпадения.
    Ответ написан
    Комментировать
  • Как сделать анимацию прорисовки линии в fabric 6?

    @eminsk
    developer python, javascripts
    Отключить кэширование объекта
    По умолчанию Fabric «кэширует» каждую фигуру в офф‑скрин канвасе для ускорения перерисовок. При анимации «динамических» свойств (как strokeDashOffset) кэш не всегда сбрасывается, поэтому ты не видишь промежуточных кадров. Решение — при создании линии сразу выключить objectCaching:
    function createLine(coords: [number, number, number, number]) {
      return new fabric.Line(coords, {
        stroke: '#000',
        strokeWidth: 2,
        originX: 'center',
        originY: 'center',
        // вот эта опция:
        objectCaching: false,
      });
    }


    Использовать requestRenderAll вместо renderAll
    Метод canvas.requestRenderAll() умнее: он при вызове внутри анимации сам батчит несколько обновлений в один кадр и гарантирует, что всё расчётное состояние Fabric будет учтено. А canvas.renderAll() может «проскочить» и отрисовать не все изменения.
    export function animateLineDraw(
      canvas: Canvas,
      line: Line,
      duration: number = 1000
    ) {
      const lineLength = Math.hypot(line.x2! - line.x1!, line.y2! - line.y1!);
    
      line.set({
        strokeDashArray: [lineLength, lineLength],
        strokeDashOffset: lineLength,
      });
    
      line.animate(
        { strokeDashOffset: 0 },
        {
          duration,
          easing: util.ease.easeInOutQuad,
          onChange: () => {
            console.log('onchange, strokeDashOffset:', line.strokeDashOffset);
            canvas.requestRenderAll();
          },
          onComplete: () => {
            console.log('oncomplete');
            line.set({
              strokeDashArray: undefined,
              strokeDashOffset: 0,
            });
            canvas.requestRenderAll();
          },
        }
      );
    }


    И убери вызов canvas.renderAll() сразу после animateLineDraw(...) — он не нужен, потому что первый кадр будет отрисован внутри onChange.
    Ответ написан
  • Как выбрать устройство вывода в audiere в C++?

    @eminsk
    developer python, javascripts
    Тут только только часть кода которая показывает, как выбрать устройство вывода не по умолчанию в Audiere без написания каких-либо циклов for или разветвлений if. Я решил сделать это через <алгоритм> из STL

    #include <audiere.h>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    #ifdef _WIN32
    #include <objbase.h>
    #endif
    
    int main() {
    #ifdef _WIN32
      CoInitialize(nullptr);
    #endif
      std::vector<audiere::AudioDeviceDesc> devices;
      devices.reserve(8); 
      audiere::GetSupportedAudioDevices(devices); 
      auto it = std::find_if(
        devices.begin(), devices.end(),
        [](auto const& desc){ return desc.name == "MyDesiredDeviceName"; }
      );
      audiere::AudioDevicePtr device(
        audiere::OpenDevice(
          it != devices.end() ? it->name.c_str() : nullptr,
          /* parameters = */ nullptr
        )
      );
    
      if (!device) {
        // Реализуй свою уже логику обработки ошибок...
        return -1;
      }
      auto sound = audiere::OpenSound(device, "music.ogg", true);
      sound->play();
    
      // ... Далее уже реализуй свою логику программы ...
    
      return 0;
    }
    Ответ написан
    Комментировать
  • Как создать .session с помощью состояния state aiogram 2.25.1?

    @eminsk
    developer python, javascripts
    aiogram 2.25.1 на этой версии уже не реализуешь просто она уже считается устаревшей и телеграмм будет работать с ошибками так как API телеграмм постоянно совершествуются.

    Я уже все переделал сделал на своих данных и все выверил. У меня уже не выскакивает эта ошибка. Проверял все на Python 3.13 и последних версиях библиотеки.
    все версии у меня библиотек там все есть на гите.

    мой код скачай https://github.com/eminsk/fix_problems_telegrambot
    в диапозитарии я не выкладывал файл свои данные а там только тестовые чтобы видеть формат записи - config.ini

    В будушем если будут проблемы создавай Pull requests если что тебе нужно потом в будущем.
    Ответ написан
    Комментировать
  • Не работает inline кнопка telebot?

    @eminsk
    developer python, javascripts
    Я пробывал в твоем коде через telebot и да тоже не реагирует не как и я тебе переделал на aiogram и все заработало.
    Ну а дальше уже сам реализовывай все остальные свои задачи.
    Работоспособность проверялась на последней версии на дату публикации python 3.13
    from __future__ import annotations
    import logging
    import os
    import shelve
    from datetime import datetime, timedelta
    from pathlib import Path
    
    from aiogram import Bot, Dispatcher, F
    from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
    from aiogram.filters import Command
    from aiogram.utils.keyboard import InlineKeyboardBuilder
    from aiogram.fsm.storage.memory import MemoryStorage
    from aiogram.client.default import DefaultBotProperties
    
    # Configure logging
    logging.basicConfig(level=logging.INFO)
    
    # Constants
    TRIAL_FLAG = "active"
    
    class UltraLiteSubBot:
        __slots__ = ("_bot", "_dp", "_prices", "_db", "_cmd_map", "_cb_map")
        def __init__(self, token: str, prices: dict[str, int], db: shelve.DbfilenameShelf):
            self._bot = Bot(token=token, default=DefaultBotProperties(parse_mode="HTML"))
            self._dp = Dispatcher(storage=MemoryStorage())
            self._prices = prices
            self._db = db
            self._cmd_map = {
                "start": self._show,
                "help": self._help
            }
            
            self._cb_map = {
                **{plan: self._plan(plan) for plan in prices},
                "activate": self._activate
            }
            self._register_handlers()
    
        def _register_handlers(self) -> None:
            self._dp.message.register(self._show, Command("start"))
            self._dp.message.register(self._help, Command("help"))
            self._dp.message.register(self._unknown)
            for plan in self._prices:
                self._dp.callback_query.register(self._plan(plan), F.data == plan)
            self._dp.callback_query.register(self._activate, F.data == "activate")
            self._dp.callback_query.register(self._unknown_callback)
    
        async def run(self) -> None:
            await self._bot.set_my_commands([
                {"command": "start", "description": "Выбрать тариф"},
                {"command": "help", "description": "Справка"}
            ])
            await self._dp.start_polling(self._bot)
        async def _show(self, msg: Message) -> None:
            uid = msg.chat.id
            builder = InlineKeyboardBuilder()
            for plan, price in self._prices.items():
                builder.button(text=f"{plan.title()} — {price}₽", callback_data=plan)
            if await self._trial_ok(uid):
                builder.button(text="Активировать пробный период", callback_data="activate")
            builder.adjust(1)
            await msg.answer("Выберите тариф:", reply_markup=builder.as_markup())
    
        async def _help(self, msg: Message) -> None:
            await msg.answer("/start — выбрать тариф\n/help — справка")
    
        async def _unknown(self, msg: Message) -> None:
            await msg.answer("Неизвестная команда. /help")
    
        async def _unknown_callback(self, call: CallbackQuery) -> None:
            await call.answer()
            await call.message.answer("Неизвестная операция.")
    
        def _plan(self, name: str):
            async def _handler(call: CallbackQuery) -> None:
                await call.answer()
                await call.message.answer(f"Вы выбрали тариф «{name}».")
            return _handler
    
        async def _activate(self, call: CallbackQuery) -> None:
            await call.answer()
            uid = str(call.from_user.id)
            try:
                self._db[uid] = {
                    "started": datetime.utcnow(),
                    TRIAL_FLAG: True,
                    "questions": 0,
                    "symbols": 0,
                }
                self._db.sync()
            except Exception as e:
                await call.message.answer(f"⚠️ Ошибка БД: {e}")
                return
    
            await call.message.answer(
                "✅ Пробный период активирован!\nДоступно: 10 вопросов / 10 000 символов"
            )
            
            try:
                await call.message.edit_reply_markup(reply_markup=None)
            except Exception:
                pass
    
        async def _trial_ok(self, uid: int) -> bool:
            rec = self._db.get(str(uid), {})
            return not rec.get(TRIAL_FLAG) or datetime.utcnow() - rec.get("started", datetime.min) >= timedelta(days=7)
    
    
    async def main():
        TOKEN = os.getenv("BOT_TOKEN", "вставь свой токен сюда")
        PRICES = {"month": 199, "quarter": 549, "year": 1_490}
        db = shelve.open(str(Path(__file__).with_name("trial.db")), writeback=True)
        db.update({k: v | {TRIAL_FLAG: v.get(TRIAL_FLAG, False)} for k, v in db.items()})
        bot = UltraLiteSubBot(TOKEN, PRICES, db)
        await bot.run()
    
    
    if __name__ == "__main__":
        import asyncio
        asyncio.run(main())
    Ответ написан
    Комментировать
  • Тkinter, после сборки pyinstaller не видит файл иконки, ошибка: bitmap "icon.ico" not defined. Как исправить?

    @eminsk
    developer python, javascripts
    Проблема в том, что когда ты компилируешь приложение в один файл (--onefile), все ресурсы упаковываются внутрь исполняемого файла и извлекаются во временную директорию во время выполнения. Путь к файлу иконки уже не соответствует тому, что был в исходном проекте.
    Используй относительные пути с правильным флагом --add-data

    pyinstaller --name Analyzer --icon=icon.ico --add-data "icon.ico;." --noconsole --onefile main.py


    теперь твоя иконка будет добавлена в сам твой файл уже
    Лично таких проблем как у тебя не было у меня.

    И чтобы бы ты представлял правильность кода:
    import os
    import sys
    import tkinter as tk
    from PIL import Image, ImageTk
    
    class AppResources:
        def __init__(self, relative_path: str):
            self.relative_path = relative_path
            self.base_path = self._get_base_path()
            self.absolute_path = self._get_absolute_path()
        
        def _get_base_path(self) -> str:
            return sys._MEIPASS if hasattr(sys, '_MEIPASS') else os.path.abspath(".")
        
        def _get_absolute_path(self) -> str:
            return os.path.join(self.base_path, self.relative_path)
        
        def load_image(self) -> ImageTk.PhotoImage:
            return ImageTk.PhotoImage(Image.open(self.absolute_path))
    
    class App(tk.Tk):
        def __init__(self, icon_path: str):
            super().__init__()
            self.icon_path = icon_path
            self._setup_ui()
        
        def _setup_ui(self):
            self.title("Optimized Tkinter App")
            self.geometry("400x300")
            self._set_icon()
        
        def _set_icon(self):
            resources = AppResources(self.icon_path)
            icon = resources.load_image()
            self.iconphoto(True, icon)
    
    if __name__ == "__main__":
        app = App("icon.ico")
        app.mainloop()
    Ответ написан
    Комментировать
  • Нахождение значения в фрейме(или столбце) и при его нахождении добавить дополнительные строки. Как реализовать код в Pandas (Python)?

    @eminsk
    developer python, javascripts
    import pandas as pd
    df = pd.DataFrame({'Name': ['car1', 'car2', 'car3', 'car4'], 'Type': [20, 21, 19, 18], 'Repair': ["n", "n", "y", "n"]})
    def add_bit_rows(df):
        y_rows = df[df['Repair'] == 'y']
        bit_rows = [
            {
                'Name': row['Name'],
                'Type': row['Type'],
                'Repair': f"y_bit{i}"
            }
            for _, row in y_rows.iterrows()
            for i in range(16)
        ]
        df_bits = pd.DataFrame(bit_rows)
        return pd.concat([df, df_bits], ignore_index=True)
    print(add_bit_rows(df))
    Ответ написан
    Комментировать
  • Какой выбрать БП?

    @eminsk
    developer python, javascripts
    Cougar STE 500W будет наиболее подходящим вариантом для твоей сборки. Он обеспечивает необходимую мощность и имеют положительные отзывы о надежности.

    Причины моего выбора для тебя:
    Надежность: Cougar зарекомендовал себя как производитель качественных блоков питания.
    Стабильность: Обеспечивает стабильное питание для твоей конфигурации.
    Отзывы: по поиску в интернете пользователи отмечают хорошую производительность и долговечность.
    Этот блок питания будет отличным выбором для твоей конфигурации твоего компьютера с Xeon E5-2650 v2 и RX 570 8GB.
    Ответ написан
  • Почему Python выдает ошибку в строке с newPosition?

    @eminsk
    developer python, javascripts
    Походу пока еще не до конца освоил как правильно писать однострочные коды.
    И всегда обязательно делай проверку на ошибку в коде и отладку кода

    alphabet = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
    
    caesar_cipher = lambda text, key: ''.join(
            alphabet[(alphabet.find(letter) + key) % len(alphabet)] if letter in alphabet else letter
            for letter in text
        )
    encrypt = input('Введите слово, которое хотите зашифровать: ')
    try:
        encrypted = caesar_cipher(encrypt, int(input('Введите ключ (от 1 до 32): ')))
        print(f'Зашифрованное слово: {encrypted}')
    except ValueError:
        print('Ошибка: ключ должен быть числом.')
    Ответ написан
    Комментировать
  • Как сделать так чтобы когда персонаж касался линии останавливался?

    @eminsk
    developer python, javascripts
    Тебе нужно в функции __init__ описать переменную self.line_y = 370
    и переделать функцию с проверкой на касание с линией
    def tick(self):
        x1, y1, x2, y2 = self.coords(self.box)
        if y2 < self.line_y:  # 
            self.move(self.box, self.dx, self.dy)
        else:
            self.dx = 0
            self.dy = 0
        self.after(self.dt, self.tick)
    Ответ написан
    Комментировать
  • Возможно ли скрыть свой IP адрес в локальной сети?

    @eminsk
    developer python, javascripts
    1. SoftEther — это многофункциональный VPN-сервер, который поддерживает различные протоколы. Он также может быть настроен для работы в локальной сети и позволяет скрывать IP-адреса.
    2. Squid — это прокси-сервер, который может быть установлен на одном из компьютеров в сети. Он позволяет перенаправлять трафик через себя и скрывать реальные IP-адреса других устройств.

    3. Данный код на python и скрывает/изменяет локальный ip адрес на твоем компьютере только или где запущен данный скрипт. по нажатии на клавишу q выход и возвращает обратно в режим DHCP
    в строчке кода замени на свое название то что в кавычках - interface = "Ethernet"
    для его использования установить на своем домашнем компьютере Python и установить библиотеку keyboard, чтобы потом для рабочего места сделать с помощью pyinstaller чтобы не ставить там python.

    import ipaddress
    import random
    import time
    import subprocess
    import platform
    import keyboard  # pip install keyboard
    import re
    
    
    class IPAddressManager:
        """Класс для управления и скрытия IP-адресов в локальной сети."""
    
        def __init__(self, interface: str):
            self.interface = interface
            self.original_ip = self._get_current_ip()
            self.hidden_ip = None
    
        def _get_current_ip(self) -> str:
            """Получить текущий IP-адрес интерфейса."""
            try:
                if platform.system() == "Windows":
                    output = subprocess.check_output(
                        "ipconfig", shell=True, stderr=subprocess.DEVNULL, universal_newlines=True)
                    pattern = re.compile(
                        rf"{self.interface}.*?IPv4.*?:\s*(\d+\.\d+\.\d+\.\d+)", re.DOTALL)
                    match = pattern.search(output)
                    if match:
                        return match.group(1)
                    raise ValueError(
                        f"IP-адрес для интерфейса {self.interface} не найден")
                else:  # Linux и macOS
                    output = subprocess.check_output(
                        f"ifconfig {self.interface}", shell=True, universal_newlines=True)
                    match = re.search(r"inet (\d+\.\d+\.\d+\.\d+)", output)
                    if match:
                        return match.group(1)
                    raise ValueError(
                        f"IP-адрес для интерфейса {self.interface} не найден")
            except subprocess.CalledProcessError as e:
                raise RuntimeError(f"Ошибка при выполнении команды: {e}")
    
        def hide_ip(self) -> None:
            """Скрыть IP-адрес, изменив его на случайный в той же подсети."""
            current_ip = ipaddress.ip_address(self.original_ip)
            network = ipaddress.ip_network(f"{current_ip}/24", strict=False)
    
            while True:
                new_ip = ipaddress.ip_address(random.randint(
                    int(network.network_address) + 1, int(network.broadcast_address) - 1))
                if new_ip != current_ip:
                    self.hidden_ip = str(new_ip)
                    break
    
            self._change_ip(self.hidden_ip)
    
        def restore_ip(self) -> None:
            """Восстановить оригинальный IP-адрес."""
            if self.hidden_ip:
                self._change_ip(self.original_ip)
                self.hidden_ip = None
    
        def _change_ip(self, new_ip: str) -> None:
            """Изменить IP-адрес интерфейса."""
            try:
                if platform.system() == "Windows":
                    subprocess.run(f'netsh interface ip set address name="{self.interface}" static {new_ip} 255.255.255.0',
                                   shell=True, check=True, stderr=subprocess.DEVNULL)
                else:  # Linux и macOS
                    subprocess.run(f"sudo ifconfig {self.interface} {new_ip} netmask 255.255.255.0",
                                   shell=True, check=True, stderr=subprocess.DEVNULL)
            except subprocess.CalledProcessError as e:
                raise RuntimeError(
                    f"Не удалось изменить IP-адрес на {new_ip}. Ошибка: {e}")
    
        def restore_dhcp(self) -> None:
            """Восстановить автоматическое получение IP-адреса (DHCP)."""
            try:
                if platform.system() == "Windows":
                    subprocess.run(
                        f'netsh interface ip set address name="{
                            self.interface}" source=dhcp',
                        shell=True, check=True, stderr=subprocess.DEVNULL
                    )
                    print(f"Интерфейс {
                          self.interface} успешно переведен в режим DHCP")
                else:  # Linux и macOS
                    subprocess.run(
                        f"sudo dhclient -r {self.interface} && sudo dhclient {self.interface}",
                        shell=True, check=True, stderr=subprocess.DEVNULL
                    )
                    print(f"Интерфейс {
                          self.interface} успешно переведен в режим DHCP")
            except subprocess.CalledProcessError as e:
                print(f"Ошибка при восстановлении DHCP: {e}")
    
        def run(self) -> None:
            """Запустить процесс скрытия IP-адреса."""
            print(f"Начальный IP-адрес: {self.original_ip}")
            self.hide_ip()
            print(f"IP-адрес скрыт. Новый адрес: {self.hidden_ip}")
            print("Нажмите 'q' для выхода и восстановления автоматического получения IP.")
    
            while True:
                if keyboard.is_pressed('q'):
                    break
                time.sleep(0.1)
    
            self.restore_dhcp()
            print("Программа завершена. DHCP восстановлен.")
    
    
    if __name__ == "__main__":
        try:
            interface = "Ethernet"  # Тут замени на имя твоего сетевого интерфейса - так как я делал это все на своем компе
            manager = IPAddressManager(interface)
            manager.run()
        except Exception as e:
            print(f"Произошла ошибка: {e}")
    Ответ написан
    6 комментариев
  • Как мне изменить шрифт на CustomTkinter?

    @eminsk
    developer python, javascripts
    import customtkinter as ctk
    
    ctk.set_appearance_mode("dark")
    
    
    class App(ctk.CTk):
        def __init__(self):
            super().__init__()
    
            self.title("Delta Search")
            self.geometry("1050x630")
    
            self.button_frame_1 = ctk.CTkFrame(self,
                                               fg_color='#333333',
                                               border_width=2,
                                               corner_radius=10,
                                               border_color='#f53333',
                                               width=915,
                                               height=50,
                                               )
            self.button_frame_1.grid(row=0, column=0, padx=50, pady=10)
    
            # тут и меняется тебе сам объект  для шрифта
            custom_font = ctk.CTkFont(family="Arial", size=20, weight="bold")
    
            self.button = ctk.CTkButton(self.button_frame_1,
                                        fg_color='#454545',
                                        text='Universal search',
                                        width=150,
                                        height=40,
                                        border_color='#f53333',
                                        corner_radius=10,
                                        border_width=1,
                                        font=custom_font  # Применить тут шрифт
                                        )
            self.button.grid(row=0, column=0, padx=(20, 2), pady=10)
    
    
    app = App()
    app.mainloop()
    Ответ написан
    Комментировать
  • Что делать, если не скачивается видео из youtube (yt_dlp)?

    @eminsk
    developer python, javascripts
    зачем тебе даже python просто скачай с официального сайта
    https://github.com/yt-dlp/yt-dlp/releases/download...

    и просто запусти yt-dlp -f bestvideo+bestaudio/best и твоя ссылка youtube
    не забывай еще скачать ffmpeg.exe
    и обновлять yt-dlp -U для выхода новых версий и все
    Тебе даже python не подобится так как скомпилировали для тебя
    Ответ написан
    4 комментария
  • Каков должен быть sys.path у чистого Python 3.1x под Windows?

    @eminsk
    developer python, javascripts
    В Windows 7 ты не как не запустишь python 3.12 и не выше 3.8
    Windows 8.x тут версии python 3.9-3.11 но не как python 3.12
    Windows XP тут версии python 3.x-3.4 и выше нельзя

    Реализация на windows 7 в твоем случае

    Python 3.8.19 (default, Mar 20 2024, 11:17:09) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> print('\n'.join(__import__('sys').path))
    
    D:\Python38\python38.zip
    D:\Python38\DLLs
    D:\Python38\lib
    D:\Python38
    D:\Python38\lib\site-packages
    Ответ написан
    Комментировать