• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья Публикация и редактирование статей на сервисе telegra.ph с помощью Python

В сети существует очень много сервисов, которые предлагают, в том или ином виде, размещение на них статей или простых заметок. Но у мессенджера Телегам есть свой сервис, и, думаю, что многие с ним знакомы — это telegra.ph. Он позволяет разместить на создаваемых страницах простой текст с базовым форматированием, добавить картинки и ссылки на какие-то источники. Более того, данный сервис не требует авторизации для размещения контента. У сервиса есть собственное API, которое позволяет автоматизировать процесс постинга, а также редактировать размещенные материалы. Давайте поговорим о том, как автоматизировать данный процесс с помощью Python.

2022-08-01_08-07.png


Давайте напишем небольшой скрипт, который позволит создавать аккаунт, публиковать статьи, а также редактировать уже опубликованные.


Что понадобится?

Для работы данного скрипта нужно установить библиотеку html-telegraph-poster, именно с ее помощью мы будем выполнять все основные операции. Для ее установки пишем в терминале:

pip install html-telegraph-poster

И на этом все. Больше сторонних скриптов нам не понадобится. После того, как библиотека для работы с API Телеграф установлена, нужно импортировать в скрипт все необходимые библиотеки. Давайте сделаем это:

Python:
import json
from pathlib import Path

from html_telegraph_poster import TelegraphPoster
from html_telegraph_poster.upload_images import upload_image


Создание аккаунта

Для того, чтобы мы имели возможность редактировать размещенные посты в любое время, а не только в рамках одной сессии, а API Телеграф позволяет получить временный токен, так как регистрация на сервисе не обязательна, нужно создать постоянный аккаунт. Создание аккаунтов здесь происходит немного странно. К примеру, можно создать хоть десять аккаунтов с одними и теми же данными. Основное различие у них будет заключаться только в токене для доступа.

Поэтому, создавать аккаунт лучше всего один раз. А в последующем пользоваться уже созданными данными.

Создадим функцию check_account(short_name: str, author: str, link: str). На вход она принимает несколько значений. short_name — Короткое имя пользователя. Именно оно отображается над кнопкой редактировать и служит для группировки статей на Телеграф. Поэтому, это обязательный параметр. author — имя автора статьи или ник. Здесь можно указать любые данные, данный параметр не является обязательным, но в рамках данного скрипта, его нужно будет ввести. link — ссылка на сайт, канал или еще куда-нибудь. Это не обязательный параметр. Служит для того, чтобы добавлять ссылку к имени автора статьи.

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

Python:
conf_dir = Path.cwd() / 'conf'
conf_file = conf_dir / author

Далее, проверим, существует ли директория, если нет, создаем. Затем создаем экземпляр класса TelegraphPoster. Проверяем, есть ли в наличии файл с токеном пользователя. Если таковой файл отсутствует, делаем запрос на создание постоянного аккаунта, в котором передаем короткое имя, имя автора и ссылку. И хотя этот параметр можно не передавать, указывать его обязательно, так как пользователь может захотеть переопределить значение данного параметра и указать нужную информацию.

Python:
    if not conf_dir.exists():
        conf_dir.mkdir()
    tph = TelegraphPoster()
    if not Path(f'{conf_file}.json').exists():
        token = tph.create_account(short_name, author, link)

В ответе от сервиса нам прилетает json, в котором содержится как та информация, которую мы передавали, так и токен для доступа к аккаунту. Еще здесь есть ссылка на редактирование статьи в браузере. Так что, можно использовать ее для того, чтобы что-то отредактировать вручную. Записываем полученные данные в json файл, после чего возвращаем из функции полученный токен.

Python:
        with open(f'{conf_file}.json', 'w', encoding='utf-8') as file:
            json.dump(token, file, indent=4, ensure_ascii=False)
        return token['access_token']

Если же файл с данными существует, открываем его, считываем токен и возвращаем его значение из функции.

Python:
    else:
        with open(f'{conf_file}.json', 'r', encoding='utf-8') as file:
            token = json.load(file)['access_token']
        return token

Python:
def check_account(short_name: str, author: str, link: str):
    """
    Функция проверки наличия аккаунта пользователя.
    Необходим для редактирования ранее опубликованных статей.
    Проверяется наличие директории с файлами конфигурации.
    Если нет - создается.
    Проверяется наличие файла конфигурации. Если нет, создается
    аккаунт, полученные данные сохраняются в json. Возвращается токен.
    Если есть, считывается токен доступа и возвращается из функции.
    :param short_name: Короткое имя пользователя, ник.
    :param author: Полное имя пользователя.
    :param link: Необязательный параметр. Ссылка на сайт или канал.
    :return: Возвращается токен, полученный при создании аккаунта.
    """
    conf_dir = Path.cwd() / 'conf'
    conf_file = conf_dir / author

    if not conf_dir.exists():
        conf_dir.mkdir()
    tph = TelegraphPoster()
    if not Path(f'{conf_file}.json').exists():
        token = tph.create_account(short_name, author, link)
        with open(f'{conf_file}.json', 'w', encoding='utf-8') as file:
            json.dump(token, file, indent=4, ensure_ascii=False)
        return token['access_token']
    else:
        with open(f'{conf_file}.json', 'r', encoding='utf-8') as file:
            token = json.load(file)['access_token']
        return token


Публикация статей в Телеграф

Создадим функцию для публикации статей в Телеграф. Я назвал ее post_public(short_name, author, path_doc, link=''). На входе данная функция получает все то же короткое имя пользователя или ник, которое является обязательным параметром. Имя автора, и ссылку, которая имеет пустое значение по умолчанию.

Для начала нужно создать экземпляр класса TelegraphPoster, в который мы передаем полученный токен доступа к аккаунту. Здесь вызывается созданная нами ранее функция для создания аккаунта. Как самостоятельная единица она не вызывается в коде нигде, а служит вспомогательной функцией для получения токена. Так что, если аккаунта нет, он будет создан. Если есть, считается и вернется токен.

Затем создаем переменную, в которой будет содержаться путь к файлу со статьей. Данный файл, для публикации, нужно правильно отформатировать, но о форматировании этого файла мы поговорим немного позже. Объявляем переменную text, в которой будет храниться статья для публикации уже считанная из файла и отформатированная нужным образом.

Python:
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''

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

Python:
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'

Из выше опубликованного кода хотелось бы выделить одну небольшую функцию, которая служит для загрузки изображений в Телеграф, чтобы в последующем можно было их использовать для вставки в текст статьи. Таким образом, когда скрипт находит в строке тег «img», он понимает, что здесь ссылка на изображение для загрузки. Создается переменная, в которую будет возвращено значение, а именно, ссылка на загруженное изображение. Инициализируем загрузку изображения на сервис. Запускаем функцию upload_image, в которую передаем ссылку на локальный файл. Помимо этого, в переменную также можно передать ссылку на изображение в интернете.

Насколько я успел поковыряться в данной функции, получив ссылку на изображение в интернете она все равно для начал его скачает, после чего будет определен ее тип, то есть, является ли она jpg или png, или еще что-то. Затем загруженное изображение будет переведено в байты и только после этого будет загружено на сервис. С локальным файлом проще. Здесь он сразу открывается в байтовом режиме, считываются данные, определяется тип и загружается на сервис.

link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")

После того, как нужный текст для публикации будет сформирован, его нужно опубликовать. Вызываем метод post класса TelegraphPoster. Здесь для публикации статьи нужно передать заголовок, автора и текста статьи. Если статьи опубликуется благополучно, в ответ прилетит json, в котором будет содержаться ключ path — короткая ссылка на статью. Она нужна будет для редактирования. И url — полная ссылка на размещенную статью. Для редактирования не нужна, нужна для репоста в телеграм или куда-то еще.

post_data = tph.post(title=title, author=author, text=text)

Полученные данные нужно сохранить в json, чтобы у нас был постоянно обновляемый список статей с заголовками и ссылками. Проверяем, есть ли такой список в директории конфигурации. Если нет, создаем его с полученными данными. Если же файл уже есть, открываем его, распаковываем в словарь, после чего обновляем словарь и сохраняем в файл, с перезаписью предыдущего. После чего выводим в терминал сообщение об успешной публикации, где указываем ссылку на статью и выходим из функции в функцию пользовательского выбора.

Python:
    if not Path(f'{author}_post.json').exists():
        post_link = {title: {'path': post_data['path'], 'url': post_data['url']}}
        with open(f'{author}_post.json', 'w', encoding='utf-8') as file:
            json.dump(post_link, file, indent=4, ensure_ascii=False)
    else:
        with open(f'{author}_post.json', 'r', encoding='utf-8') as file:
            post_link = dict(json.load(file))
            post_link.update({title: {'path': post_data['path'], 'url': post_data['url']}})
            with open(f'{author}_post.json', 'w', encoding='utf-8') as fil:
                json.dump(post_link, fil, indent=4, ensure_ascii=False)
    print(f'\nСтатья: "{title}" опубликована. Ссылка на статью: {post_data["url"]}')
    change(short_name, author, link)
    return

Python:
def post_public(short_name, author, path_doc, link=''):
    """
    Создается объект класса, в который передается токен,
    получаемый с помощью функции.
    В переменную присваивается путь к файлу со статьей.
    Объявляется переменная text, в которой будет содержаться
    отформатированная статья.
    Построчно считывается статья. В каждой строке ищутся определенные
    теги, в зависимости от которых выполняется форматирование текста.
    Публикуется статья. Передаются параметры заголовка, автор, текст статьи.
    Проверяется, есть ли файл с опубликованными статьями. Если нет, создается.
    В него записывается заголовок статьи, а также полученные данные при создании:
    path: короткая ссылка на статью, url: полная ссылка на статью.
    Если файл существует, считываются данные, конвертируются в словарь. Обновляются,
    после чего файл перезаписывается с новыми данными.
    Выводиться сообщение о публикации. Запускается функция выбора.
    :param short_name: Короткое имя пользователя, ник.
    :param author: Полное имя пользователя.
    :param path_doc: Путь к файлу со статьей.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершает выполнение функции при возврате в меню выбора.
    """
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'

    post_data = tph.post(title=title, author=author, text=text)
    if not Path(f'{author}_post.json').exists():
        post_link = {title: {'path': post_data['path'], 'url': post_data['url']}}
        with open(f'{author}_post.json', 'w', encoding='utf-8') as file:
            json.dump(post_link, file, indent=4, ensure_ascii=False)
    else:
        with open(f'{author}_post.json', 'r', encoding='utf-8') as file:
            post_link = dict(json.load(file))
            post_link.update({title: {'path': post_data['path'], 'url': post_data['url']}})
            with open(f'{author}_post.json', 'w', encoding='utf-8') as fil:
                json.dump(post_link, fil, indent=4, ensure_ascii=False)
    print(f'\nСтатья: "{title}" опубликована. Ссылка на статью: {post_data["url"]}')
    change(short_name, author, link)
    return


Редактирование опубликованной статьи

Для редактирования опубликованной статьи создадим функцию post_edit(short_name, author, path_doc, link=''), которая также как и предыдущая будет принимать короткое имя пользователя, или ник, имя автора, ссылку на файл для публикации и ссылку на сайт или канал, для которой установлено значение по умолчанию, так как она не является обязательным параметром.

Создаем экземпляр класса TelegraphPoster, в который передаем полученный ранее токен. Его мы также получаем с помощью функции создания аккаунта. Создаем переменную с путем к файлу со статьей. Объявляем пустую переменную text. В нее будет помещена отформатированная статья.

Python:
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''

Теперь построчно считываем содержимое файла со статьей и ищем наличие определенных тегов. В соответствии с найденными тегами выполняем форматирование текста. И помещаем отформатированный текст в переменную созданную для этого ранее — text. С изображениями здесь происходит все то же самое. Выполняется загрузка изображения, получение ссылки и уже только после этого добавляется отформатированный текст в переменную.

Python:
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'

Открываем для чтения файл со ссылками на статьи. Следует упомянуть, что статья может полностью поменять содержание, но заголовок ее должен остаться прежним. В нем ищем по заголовку из файла статьи ссылку на ранее опубликованную, забираем значение параметра path, который содержит короткую ссылку на опубликованную статью. Именно поэтому заголовок статьи, если вы редактируете файл, должен совпадать с тем заголовком, что был у статьи ранее. Если заголовок не находиться, выводиться сообщение об отсутствии статьи в ранее опубликованных и происходит выход из функции редактирования в функцию пользовательского выбора.

Python:
    with open(f'{author}_post.json', 'r', encoding='utf-8') as fil:
        posts = json.load(fil)
        try:
            path = f'/{posts[title]["path"]}'
        except KeyError:
            print('Данная статьи отсутствует в опубликованных')
            change(short_name, author, link)
            return

Если же все совпадает и найдено корректно, запускается метод edit, в который передается заголовок статьи, ее текст, и короткая ссылка на статью, которая должна содержать перед собой прямой слэш. После чего выводиться сообщение о редактировании и ссылка на отредактированную статью. Ссылка не изменяется, а остается прежней, как и у ранее опубликованной статьи. А далее функция завершает свою работу и запускается функция пользовательского выбора.

Python:
    edit_post = tph.edit(title=title, text=text, path=path)
    print(f'\nСтатья: "{title}" отредактирована. Ссылка на статью: {edit_post["url"]}')
    change(short_name, author, link)
    return

Python:
def post_edit(short_name, author, path_doc, link=''):
    """
    Создается объект класса, в который передается токен.
    Переменной doc присваивается объект, содержащий путь к файлу со статьей.
    Объявляется переменная text, в которой будет храниться отформатированная статья.
    Построчно считываются данные из файла со статьей. В каждой строке ищутся
    определенные теги, в зависимости от которых форматируется текст.
    Открывается файл с опубликованными статьями. Ищется по заголовку из файла со статьей
    короткая ссылка. Формируется для редактирования.
    Выполняется редактирование статьи. Передается заголовок, текст и короткая ссылка на статью.
    Выводиться сообщение о публикации.
    Запускается функция выбора действий, после чего работа функции завершается.
    :param short_name: Короткое имя автора, ник.
    :param author: Полное имя автора.
    :param path_doc: Путь к статье с изменениями.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершает выполнение функции.
    """
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'
    with open(f'{author}_post.json', 'r', encoding='utf-8') as fil:
        posts = json.load(fil)
        try:
            path = f'/{posts[title]["path"]}'
        except KeyError:
            print('Данная статьи отсутствует в опубликованных')
            change(short_name, author, link)
            return
    edit_post = tph.edit(title=title, text=text, path=path)
    print(f'\nСтатья: "{title}" отредактирована. Ссылка на статью: {edit_post["url"]}')
    change(short_name, author, link)
    return


Обработка пользовательского выбора

Создадим функцию change(short_name, author, link), которая принимает значение короткого имени, имени автора и ссылку на сайт или канал. Здесь пользователю предлагается на выбор несколько действий. А именно: публикация статьи, редактирование статьи, ввод новых данных пользователя и выход из скрипта.

В зависимости от того, что выберет пользователь, запускается та или иная функция. А перед запуском функция публикации или редактирования статьи запрашивается путь к файлу со статьей.

Python:
def change(short_name, author, link):
    """
    Запрашивается выбор действия пользователя. В зависимости от выбора
    запускается функция. Перед этим запрашивается путь к файлу со статьей.
    Также возможно выбрать изменение параметров короткого имени автора, полного имени,
    ссылки. Или выход из скрипта.
    :param short_name: Короткое имя автора, ник.
    :param author: Полное имя автора.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершение работы функции.
    """
    user_change = input('\nВыберите действие:\n   [1] Публикация статьи\n   [2] Редактирование статьи\n   '
                        '[3] Ввести новые данные\n   [4] Выход\n   >>> ')

    if user_change == "1":
        path_doc = input('Введите ссылку на файл со статьей: ')
        if not Path(path_doc).exists():
            print('Файл не существует.')
            return
        post_public(short_name, author, path_doc, link)
    elif user_change == "2":
        path_doc = input('\nВведите ссылку на файл с отредактированной статьей: ')
        if not Path(path_doc).exists():
            print('Файл не существует.')
            return
        post_edit(short_name, author, path_doc, link)
    elif user_change == "3":
        main()
        return
    elif user_change == "4":
        print('\nBy-by!')
        exit(0)


Стартовая функция

Данная функция запускается при старте скрипта. Создадим функцию main(). Никаких параметров она не принимает. Здесь у пользователя запрашиваются данные, которые будут необходимы для работы остальных функций скрипта, а именно: короткое имя или ник, имя автора, ссылка на сайт или канал, которая является необязательным параметром, потому вместо нее может передаться пустое значение. После чего, полученные значение передаются в функцию обработки пользовательского выбора.

Python:
def main():
    """
    Запрашиваются параметры: короткое имя, ник; полное имя автора;
    ссылка на сайт или канал.
    Запускается функция обработки пользовательского выбора, в которую
    передаются полученные данные.
    """
    short_name = input('Введите короткое имя аккаунта: ')
    author = input('Введите имя автора статьи: ')
    link = input('Введите ссылку на сайт или канал (необязательный параметр): ' or '')
    change(short_name, author, link)


Формат файла со статьей для публикации

Для того, чтобы опубликовать статью, нам нужно создать файл в нужном формате, где будет указано, к какому типу принадлежит та или иная строка с текстом. Для примера, строка с заголовком будет иметь тег title, после будет идти разделитель «|», по которому и будет производиться дальнейшая обработка в функциях скрипта.

title|Тестовый пост

Если же необходимо в тексте создать ссылку на сторонний ресурс, придется указать его явно. То есть, здесь же в тексте нужно будет указать html-разметку. Для примера:

text|Еще какой-то текст <a href="https://wm-school.ru/">Перейти на сайт wm-school</a>

Если же вам нужно вставить в статью изображение, указываем тег img, затем разделитель «|» и путь к изображению. Полный или относительный. Тут уже зависит от того, где у вас расположено изображение.

img|/media/test/telegraph/pic2.jpg

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

Пример структуры текстового файла со статьей:

Код:
title|Тестовый пост
text|Какой-то текст
text|Еще какой-то текст <a href="https://wm-school.ru/">Перейти на сайт wm-school</a>
img|/media/test/telegraph/pic2.jpg
text|Еще какой-то текст


Заключение

Как мы видим, публикация статей на сервисе telegra.ph в автоматическом режиме является не таким уж сложным занятием с использованием нужных библиотек. В действительности, если бы вы захотели опубликовать статью с помощью обычного requests, а это тоже возможно, текст статьи, то есть ее html-разметку необходимо было бы преобразовать в формат Array of Node, up to 64 KB. То есть, если бы вы просто написали текст «Привет, это я», и попытались бы опубликовать его в виде статьи, у вас бы ничего не получилось. Для примера, ниже приведена разметка, в которую нужно преобразовать текст.

Код:
[
  {
  "tag": "b",
  "children": ["Привет, это я"]
  }
]

То есть, для начала вам нужно сделать html-разметку текста, для примера, а после преобразовать ее вот в такой вот формат. К счастью, библиотека html-telegraph-poster делает это автоматически. Тот, кто создавал ее, с помощью регулярных выражений ищет и преобразовывает самые разнообразные теги. Поэтому с разметкой, на самом деле можно поэкспериментировать, так как в документации не описано, какие именно теги поддерживает данная библиотека.

Python:
"""
Данный скрипт выполняет публикацию или редактирование статей
на сайте телеграф. Вспомогательный сайт для публикации простых
статей Телеграмм. Для работы данной функции необходимо установить
следующую библиотеку: pip install html-telegraph-poster

Для корректной публикации статей требуется создание текстового файла
с отформатированным содержимым. В содержимом поддерживаются теги: title,
text, img. Для создания ссылки необходимо явно создать в тексте html.
Пример файла:

title|Тестовый пост2
text|Какой-то текст
text|Еще какой-то текст <a href="https://wm-school.ru/">Перейти на сайт wm-school</a>
img|/media/vev/PROJECT/Projects/Python для SEO специалиста/telegraph/pic2.jpg
text|Еще какой-то текст
"""

import json
from pathlib import Path

from html_telegraph_poster import TelegraphPoster
from html_telegraph_poster.upload_images import upload_image


def check_account(short_name: str, author: str, link: str):
    """
    Функция проверки наличия аккаунта пользователя.
    Необходим для редактирования ранее опубликованных статей.
    Проверяется наличие директории с файлами конфигурации.
    Если нет - создается.
    Проверяется наличие файла конфигурации. Если нет, создается
    аккаунт, полученные данные сохраняются в json. Возвращается токен.
    Если есть, считывается токен доступа и возвращается из функции.
    :param short_name: Короткое имя пользователя, ник.
    :param author: Полное имя пользователя.
    :param link: Необязательный параметр. Ссылка на сайт или канал.
    :return: Возвращается токен, полученный при создании аккаунта.
    """
    conf_dir = Path.cwd() / 'conf'
    conf_file = conf_dir / author

    if not conf_dir.exists():
        conf_dir.mkdir()
    tph = TelegraphPoster()
    if not Path(f'{conf_file}.json').exists():
        token = tph.create_account(short_name, author, link)
        with open(f'{conf_file}.json', 'w', encoding='utf-8') as file:
            json.dump(token, file, indent=4, ensure_ascii=False)
        return token['access_token']
    else:
        with open(f'{conf_file}.json', 'r', encoding='utf-8') as file:
            token = json.load(file)['access_token']
        return token


def post_public(short_name, author, path_doc, link=''):
    """
    Создается объект класса, в который передается токен,
    получаемый с помощью функции.
    В переменную присваивается путь к файлу со статьей.
    Объявляется переменная text, в которой будет содержаться
    отформатированная статья.
    Построчно считывается статья. В каждой строке ищутся определенные
    теги, в зависимости от которых выполняется форматирование текста.
    Публикуется статья. Передаются параметры заголовка, автор, текст статьи.
    Проверяется, есть ли файл с опубликованными статьями. Если нет, создается.
    В него записывается заголовок статьи, а также полученные данные при создании:
    path: короткая ссылка на статью, url: полная ссылка на статью.
    Если файл существует, считываются данные, конвертируются в словарь. Обновляются,
    после чего файл перезаписывается с новыми данными.
    Выводиться сообщение о публикации. Запускается функция выбора.
    :param short_name: Короткое имя пользователя, ник.
    :param author: Полное имя пользователя.
    :param path_doc: Путь к файлу со статьей.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершает выполнение функции при возврате в меню выбора.
    """
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'

    post_data = tph.post(title=title, author=author, text=text)
    if not Path(f'{author}_post.json').exists():
        post_link = {title: {'path': post_data['path'], 'url': post_data['url']}}
        with open(f'{author}_post.json', 'w', encoding='utf-8') as file:
            json.dump(post_link, file, indent=4, ensure_ascii=False)
    else:
        with open(f'{author}_post.json', 'r', encoding='utf-8') as file:
            post_link = dict(json.load(file))
            post_link.update({title: {'path': post_data['path'], 'url': post_data['url']}})
            with open(f'{author}_post.json', 'w', encoding='utf-8') as fil:
                json.dump(post_link, fil, indent=4, ensure_ascii=False)
    print(f'\nСтатья: "{title}" опубликована. Ссылка на статью: {post_data["url"]}')
    change(short_name, author, link)
    return


def post_edit(short_name, author, path_doc, link=''):
    """
    Создается объект класса, в который передается токен.
    Переменной doc присваивается объект, содержащий путь к файлу со статьей.
    Объявляется переменная text, в которой будет храниться отформатированная статья.
    Построчно считываются данные из файла со статьей. В каждой строке ищутся
    определенные теги, в зависимости от которых форматируется текст.
    Открывается файл с опубликованными статьями. Ищется по заголовку из файла со статьей
    короткая ссылка. Формируется для редактирования.
    Выполняется редактирование статьи. Передается заголовок, текст и короткая ссылка на статью.
    Выводиться сообщение о публикации.
    Запускается функция выбора действий, после чего работа функции завершается.
    :param short_name: Короткое имя автора, ник.
    :param author: Полное имя автора.
    :param path_doc: Путь к статье с изменениями.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершает выполнение функции.
    """
    tph = TelegraphPoster(access_token=check_account(short_name, author, link=link))
    doc = Path(path_doc)
    text = ''
    with open(doc, 'r', encoding='utf-8') as file:
        text_post = file.readlines()
        for line in text_post:
            if 'title' in line.strip():
                title = line.strip().split("|")[1]
            if 'text' in line.strip():
                text = text + f"<p>{line.strip().split('|')[1]}</p>"
            if 'img' in line.strip():
                link_img = (upload_image(line.strip().split("|")[1])).replace("http://telegra.ph", "")
                text = text + f'<img src="{link_img}">'
    with open(f'{author}_post.json', 'r', encoding='utf-8') as fil:
        posts = json.load(fil)
        try:
            path = f'/{posts[title]["path"]}'
        except KeyError:
            print('Данная статьи отсутствует в опубликованных')
            change(short_name, author, link)
            return
    edit_post = tph.edit(title=title, text=text, path=path)
    print(f'\nСтатья: "{title}" отредактирована. Ссылка на статью: {edit_post["url"]}')
    change(short_name, author, link)
    return


def change(short_name, author, link):
    """
    Запрашивается выбор действия пользователя. В зависимости от выбора
    запускается функция. Перед этим запрашивается путь к файлу со статьей.
    Также возможно выбрать изменение параметров короткого имени автора, полного имени,
    ссылки. Или выход из скрипта.
    :param short_name: Короткое имя автора, ник.
    :param author: Полное имя автора.
    :param link: Ссылка на сайт или канал. Необязательный параметр.
    :return: Завершение работы функции.
    """
    user_change = input('\nВыберите действие:\n   [1] Публикация статьи\n   [2] Редактирование статьи\n   '
                        '[3] Ввести новые данные\n   [4] Выход\n   >>> ')

    if user_change == "1":
        path_doc = input('Введите ссылку на файл со статьей: ')
        if not Path(path_doc).exists():
            print('Файл не существует.')
            return
        post_public(short_name, author, path_doc, link)
    elif user_change == "2":
        path_doc = input('\nВведите ссылку на файл с отредактированной статьей: ')
        if not Path(path_doc).exists():
            print('Файл не существует.')
            return
        post_edit(short_name, author, path_doc, link)
    elif user_change == "3":
        main()
        return
    elif user_change == "4":
        print('\nBy-by!')
        exit(0)


def main():
    """
    Запрашиваются параметры: короткое имя, ник; полное имя автора;
    ссылка на сайт или канал.
    Запускается функция обработки пользовательского выбора, в которую
    передаются полученные данные.
    """
    short_name = input('Введите короткое имя аккаунта: ')
    author = input('Введите имя автора статьи: ')
    link = input('Введите ссылку на сайт или канал (необязательный параметр): ' or '')
    change(short_name, author, link)


if __name__ == "__main__":
    main()

А на этом, пожалуй, все.

Спасибо за внимание. Надеюсь, данная информация будет вам полезна
 
Последнее редактирование модератором:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!