# deal_latex | Marsho AI
Kawaii, Intelligent and Easy to Extend

Skip to content

# Module `nonebot_plugin_marshoai.deal_latex` ​

此文件援引并改编自 nonebot-plugin-latex 数据类 源项目地址: https://github.com/EillesWan/nonebot-plugin-latex

Copyright (c) 2024 金羿Eilles nonebot-plugin-latex is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details.

### class `ConvertChannel` ​

#### async func `get_to_convert(self, latex_code: str, dpi: int = 600, fgcolour: str = '000000', timeout: int = 5, retry: int = 3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]` ​

Source code or View on GitHub
python

    async def get_to_convert(self, latex_code: str, dpi: int=600, fgcolour: str='000000', timeout: int=5, retry: int=3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
        return (False, '请勿直接调用母类')

`@staticmethod`

#### async func `channel_test() -> int` ​

Source code or View on GitHub
python

    @staticmethod
    async def channel_test() -> int:
        return -1

#### attr `URL: str = NO_DEFAULT` ​

### class `L2PChannel(ConvertChannel)` ​

#### async func `get_to_convert(self, latex_code: str, dpi: int = 600, fgcolour: str = '000000', timeout: int = 5, retry: int = 3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]` ​

Source code or View on GitHub
python

    async def get_to_convert(self, latex_code: str, dpi: int=600, fgcolour: str='000000', timeout: int=5, retry: int=3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
        async with httpx.AsyncClient(timeout=timeout, verify=False) as client:
            while retry > 0:
                try:
                    post_response = await client.post(self.URL + '/api/convert', json={'auth': {'user': 'guest', 'password': 'guest'}, 'latex': latex_code, 'resolution': dpi, 'color': fgcolour})
                    if post_response.status_code == 200:
                        if (json_response := post_response.json())['result-message'] == 'success':
                            if (get_response := (await client.get(self.URL + json_response['url']))).status_code == 200:
                                return (True, get_response.content)
                        else:
                            return (False, json_response['result-message'])
                    retry -= 1
                except httpx.TimeoutException:
                    retry -= 1
            raise ConnectionError('服务不可用')
        return (False, '未知错误')

`@staticmethod`

#### async func `channel_test() -> int` ​

Source code or View on GitHub
python

    @staticmethod
    async def channel_test() -> int:
        async with httpx.AsyncClient(timeout=5, verify=False) as client:
            try:
                start_time = time.time_ns()
                latex2png = (await client.get('http://www.latex2png.com{}' + (await client.post('http://www.latex2png.com/api/convert', json={'auth': {'user': 'guest', 'password': 'guest'}, 'latex': '\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}\n', 'resolution': 600, 'color': '000000'})).json()['url']), time.time_ns() - start_time)
            except:
                return 99999
        if latex2png[0].status_code == 200:
            return latex2png[1]
        else:
            return 99999

#### attr `URL = 'http://www.latex2png.com'` ​

### class `CDCChannel(ConvertChannel)` ​

#### async func `get_to_convert(self, latex_code: str, dpi: int = 600, fgcolour: str = '000000', timeout: int = 5, retry: int = 3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]` ​

Source code or View on GitHub
python

    async def get_to_convert(self, latex_code: str, dpi: int=600, fgcolour: str='000000', timeout: int=5, retry: int=3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
        async with httpx.AsyncClient(timeout=timeout, verify=False) as client:
            while retry > 0:
                try:
                    response = await client.get(self.URL + '/png.image?\\huge&space;\\dpi{' + str(dpi) + '}\\fg{' + fgcolour + '}' + latex_code)
                    if response.status_code == 200:
                        return (True, response.content)
                    else:
                        return (False, response.content)
                    retry -= 1
                except httpx.TimeoutException:
                    retry -= 1
        return (False, '未知错误')

`@staticmethod`

#### async func `channel_test() -> int` ​

Source code or View on GitHub
python

    @staticmethod
    async def channel_test() -> int:
        async with httpx.AsyncClient(timeout=5, verify=False) as client:
            try:
                start_time = time.time_ns()
                codecogs = (await client.get('https://latex.codecogs.com/png.image?\\huge%20\\dpi{600}\\\\int_{a}^{b}x^2\\\\,dx=\\\\frac{b^3}{3}-\\\\frac{a^3}{5}'), time.time_ns() - start_time)
            except:
                return 99999
        if codecogs[0].status_code == 200:
            return codecogs[1]
        else:
            return 99999

#### attr `URL = 'https://latex.codecogs.com'` ​

### class `JRTChannel(ConvertChannel)` ​

#### async func `get_to_convert(self, latex_code: str, dpi: int = 600, fgcolour: str = '000000', timeout: int = 5, retry: int = 3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]` ​

Source code or View on GitHub
python

    async def get_to_convert(self, latex_code: str, dpi: int=600, fgcolour: str='000000', timeout: int=5, retry: int=3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
        async with httpx.AsyncClient(timeout=timeout, verify=False) as client:
            while retry > 0:
                try:
                    post_response = await client.post(self.URL + '/default/latex2image', json={'latexInput': latex_code, 'outputFormat': 'PNG', 'outputScale': '{}%'.format(dpi / 3 * 5)})
                    if post_response.status_code == 200:
                        if not (json_response := post_response.json())['error']:
                            if (get_response := (await client.get(json_response['imageUrl']))).status_code == 200:
                                return (True, get_response.content)
                        else:
                            return (False, json_response['error'])
                    retry -= 1
                except httpx.TimeoutException:
                    retry -= 1
            raise ConnectionError('服务不可用')
        return (False, '未知错误')

`@staticmethod`

#### async func `channel_test() -> int` ​

Source code or View on GitHub
python

    @staticmethod
    async def channel_test() -> int:
        async with httpx.AsyncClient(timeout=5, verify=False) as client:
            try:
                start_time = time.time_ns()
                joeraut = (await client.get((await client.post('http://www.latex2png.com/api/convert', json={'latexInput': '\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}', 'outputFormat': 'PNG', 'outputScale': '1000%'})).json()['imageUrl']), time.time_ns() - start_time)
            except:
                return 99999
        if joeraut[0].status_code == 200:
            return joeraut[1]
        else:
            return 99999

#### attr `URL = 'https://latex2image.joeraut.com'` ​

### class `ConvertLatex` ​

#### func `__init__(self, channel: Optional[ConvertChannel] = None)` ​

Source code or View on GitHub
python

    def __init__(self, channel: Optional[ConvertChannel]=None):
        logger.info('LaTeX 转换服务将在 Bot 连接时异步加载')

#### async func `load_channel(self, channel: ConvertChannel | None = None) -> None` ​

Source code or View on GitHub
python

    async def load_channel(self, channel: ConvertChannel | None=None) -> None:
        if channel is None:
            logger.info('正在选择 LaTeX 转换服务频道，请稍等...')
            self.channel = await self.auto_choose_channel()
            logger.info(f'已选择 {self.channel.__class__.__name__} 服务频道')
        else:
            self.channel = channel

#### async func `generate_png(self, latex: str, dpi: int = 600, foreground_colour: str = '000000', timeout_: int = 5, retry_: int = 3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]` ​

Description: LaTeX 在线渲染

Source code or View on GitHub
python

    async def generate_png(self, latex: str, dpi: int=600, foreground_colour: str='000000', timeout_: int=5, retry_: int=3) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
        return await self.channel.get_to_convert(latex, dpi, foreground_colour, timeout_, retry_)

`@staticmethod`

#### async func `auto_choose_channel() -> ConvertChannel` ​

Source code or View on GitHub
python

    @staticmethod
    async def auto_choose_channel() -> ConvertChannel:

        async def channel_test_wrapper(channel: type[ConvertChannel]) -> Tuple[int, type[ConvertChannel]]:
            score = await channel.channel_test()
            return (score, channel)
        results = await asyncio.gather(*(channel_test_wrapper(channel) for channel in channel_list))
        best_channel = min(results, key=lambda x: x[0])[1]
        return best_channel()

#### attr `channel: ConvertChannel = NO_DEFAULT` ​