Пример #1
0
import asyncio
import os
import re
from aiotg import Bot, Chat
from collections import defaultdict, deque
from pprint import pprint
from datetime import datetime, timedelta

bot = Bot(api_token=os.environ['API_KEY'])
last_msgs = defaultdict(lambda: deque(maxlen=10))


def find_original(message):
    if 'text' in message:
        return message['text']
    elif 'caption' in message:
        return message['caption']

    return None


async def doit(chat, match):
    date = datetime.fromtimestamp(chat.message['date'])
    if date < datetime.now() - timedelta(minutes=5):
        print('ignoring old message from', date)
        return

    fr = match.group(1)
    to = match.group(2)
    to = (to.replace('\\/', '/').replace('\\0', '\\g<0>'))
    try:
Пример #2
0
import pytest
import random

from aiotg import Bot, Chat, InlineQuery
from aiotg import MESSAGE_TYPES, MESSAGE_UPDATES
from aiotg.mock import MockBot
from testfixtures import LogCapture

API_TOKEN = "test_token"
bot = Bot(API_TOKEN)


def custom_msg(msg):
    template = {
        "message_id": 0,
        "from": {
            "first_name": "John"
        },
        "chat": {
            "id": 0,
            "type": "private"
        }
    }
    template.update(msg)
    return template


def text_msg(text):
    return custom_msg({"text": text})

Пример #3
0
import os
import asyncio
from aiotg import Bot

bot = Bot(os.environ["API_TOKEN"])
channel = bot.channel(os.environ["CHANNEL"])
private = bot.private(os.environ["PRIVATE"])

async def greeter():
    await channel.send_text("Hello from channel!")
    await private.send_text("Why not say hello directly?")

loop = asyncio.get_event_loop()
loop.run_until_complete(greeter())
Пример #4
0
import os
import aiohttp
from aiotg import Bot

bot = Bot(os.environ["API_TOKEN"])


@bot.command(r"bitcoin")
async def bitcoin(chat, match):
    url = "https://api.bitcoinaverage.com/ticker/global/USD/"
    async with aiohttp.get(url) as s:
        info = await s.json()
        await chat.send_text(info["24h_avg"])

if __name__ == '__main__':
    bot.run()
Пример #5
0
from uuid import uuid4
from aiotg import Bot, Chat
from asyncio import Queue
from alerter.config import TELEGRAM_TOKEN
from alerter.Subscribers import Subscriber
from alerter.BaseClasses import Manager

PIN_TYPE = "telegram"


HELP_MSG = """/subscriptions - show you current subscriptions (could you unsubscribe)
/subscribe [regex] - subscribe on all notifications or part, examples: /subscribe, /subscribe _uat, /subscribe RC180312
"""

assert TELEGRAM_TOKEN
bot = Bot(api_token=TELEGRAM_TOKEN)


def inl_button(text, callback_name):
    return {
        'type': 'InlineKeyboardButton',
        'text': text,
        'callback_data': '%s' % (callback_name),
    }


def get_subscribe_markup(source_types, callback_name):
    return {
        'type': 'ReplyKeyboardMarkup',
        'inline_keyboard': [
            [inl_button(source_type, '%s-%s' % (callback_name, source_type))]
Пример #6
0
import datetime
import os

from aiotg import Bot, Chat

bot = Bot(api_token=os.getenv('TOKEN', ''))

base_phrase = "Do you ask me about deploy to prod?\n"


@bot.command(r".*")
def echo(chat: Chat, match):
    date = datetime.date.today()
    day_x = datetime.date(year=2019, month=3, day=14,)
    if date == day_x:
        return chat.reply("NO, YOU CAN'T TODAY!")
    else:
        return chat.reply("Yes, ofcourse, if tests are good and you want to.")


bot.run()
Пример #7
0
class PytrackTelegramBot(object):
    def __init__(self):
        self.connection = Connection(YOUTRACK_BASE_URL,
                                     login=YOUTRACK_LOGIN,
                                     password=YOUTRACK_PASSWORD)
        self.bot = Bot(TELEGRAM_API_KEY)
        self.db_pool = None
        self.update_timer = None
        self.logger = logging.getLogger('TG-bot')

    async def init(self):
        """
        Initializes app
        """
        self.logger.info("Initializing")
        self.db_pool = await db.create_pool(POSTGRESQL_DSN)
        projects = await self.connection.get_projects()
        _users = await self.connection.get_users()
        users = []
        for _user in _users:
            user = await self.connection.get_user(_user['login'])
            users.append((user['login'], user['fullName']))

        async with self.db_pool.acquire() as conn:
            await db.ensure_projects_are_present(conn, projects)
            await db.ensure_users_are_present(conn, users)

    async def run(self):
        #self.logger.info("Starting timer")
        #self.update_timer = aiotools.create_timer(
        #    self.check_for_updates, 300.0)
        await self.check_for_updates(30)

    async def shutdown(self):
        self.logger.info("Shutting down")
        del self.bot
        await self.db_pool.close()
        if self.update_timer:
            self.update_timer.cancel()
            await self.update_timer

    def create_mention(self, user):
        if user['tg_id']:
            return "[%s](tg://user?id=%s)" % (user['full_name'], user['tg_id'])
        else:
            return "@%s" % user['youtrack_id']

    def create_issue_link(self, issue_id):
        return "[{0}]({1}/issue/{0})".format(issue_id, YOUTRACK_BASE_URL)

    def render_message(self, mention, comment):
        return MESSAGE_TEMPLATE % (mention,
                                   self.create_issue_link(
                                       comment['issueId']), comment['text'])

    def render_change_message(self, mention, issue, change):
        updated_tmpl = "- {0}: {1} -> {2}"
        updates = (updated_tmpl.format(
            field.name, field.old_value[0] if field.old_value else "n/a",
            field.new_value[0] if field.new_value else "n/a")
                   for field in change.fields)
        updates = "\n".join(updates)
        return MESSAGE_CHANGE_TEMPLATE % (
            mention, self.create_issue_link(issue['id']), updates)

    async def try_post_markdown(self, chat, message):
        try:
            await chat.send_text(message, parse_mode='Markdown')
        except BotApiError:
            self.logger.warning(
                "Cannot send message '%s' as markdown, resending as text",
                message)
            await chat.send_text(message)

    async def post_comment(self, comment):
        async with self.db_pool.acquire() as conn:
            project_id = comment['issueId'].split('-')[0]
            chat_id = await db.get_project_chat_id(conn, project_id)
            user = await db.get_user(conn, comment['author'])
            mention = self.create_mention(user)
            message = self.render_message(mention, comment)
            self.logger.info("Posting comment %s to chat %s", comment['id'],
                             chat_id)
            chat = self.bot.channel(chat_id)
            await self.try_post_markdown(chat, message)
            await db.set_comment_posted(conn, comment)

    async def post_change(self, issue, change):
        async with self.db_pool.acquire() as conn:
            project_id = issue['id'].split('-')[0]
            chat_id = await db.get_project_chat_id(conn, project_id)
            user = await db.get_user(conn, change.updater_name)
            mention = self.create_mention(user)
            message = self.render_change_message(mention, issue, change)
            self.logger.info("Posting issue %s change to chat %s", issue['id'],
                             chat_id)
            chat = self.bot.channel(chat_id)
            await self.try_post_markdown(chat, message)

    async def post_new_issue(self, issue):
        async with self.db_pool.acquire() as conn:
            project_id = issue['id'].split('-')[0]
            user = await db.get_user(conn, issue['reporterName'])
            chat_id = await db.get_project_chat_id(conn, project_id)
            mention = self.create_mention(user)
            issue_link = self.create_issue_link(issue['id'])
            summary = issue['summary']
            issue_type = issue['Type']
            assignee = issue.get('Assignee', None)
            assignee_mention = None
            if assignee:
                try:
                    assignee_mention = self.create_mention(await db.get_user(
                        conn, assignee))
                except:
                    self.logger.warning("Could not create assignee mention")

            if assignee_mention:
                message = f"{mention} создал задачу {issue_link}: {summary} с типом {issue_type}. Задача назначена на {assignee_mention}."
            else:
                message = f"{mention} создал задачу {issue_link}: {summary} с типом {issue_type}."
            chat = self.bot.channel(chat_id)
            await self.try_post_markdown(chat, message)

    async def check_issue(self, issue, last_updated):
        self.logger.info("Checking issue %s", issue['id'])
        last_checked = 0
        project_id = issue['id'].split('-')[0]
        async with self.db_pool.acquire() as conn:
            created = int(issue['created'])
            if created > last_updated:
                # new issue
                last_checked = max(last_checked, created)
                await self.post_new_issue(issue)
            if issue['commentsCount']:
                comments = await self.connection.get_comments(issue['id'])
                for comment in comments:
                    posted = await db.check_comment(conn, comment)
                    if posted:
                        continue
                    updated = comment.get('updated',
                                          comment.get('created', '0'))
                    updated = int(updated)
                    if updated <= last_updated:
                        self.logger.info('Skipping old comment %s',
                                         comment['id'])
                        continue
                    last_checked = max(last_checked, updated)
                    await self.post_comment(comment)
            changes = await self.connection.get_changes_for_issue(issue['id'])
            for change in changes:
                print(change)
                updated = int(change.updated)
                if updated <= last_updated:
                    self.logger.info('Skipping old change for issue %s',
                                     issue['id'])
                    continue
                last_checked = max(last_checked, updated)
                await self.post_change(issue, change)
            if last_checked > 0:
                last_checked = datetime.datetime.fromtimestamp(last_checked /
                                                               1000)
                await db.set_last_updated(conn, project_id, last_checked)

    async def check_project(self, project, limit=50):
        self.logger.info("Checking project %s", project['youtrack_id'])
        try:
            timestamp = project['last_checked'].timestamp()
            current = 0
            while True:
                issues = await self.connection.get_issues(
                    project['youtrack_id'],
                    project['search_query'],
                    current,
                    limit,
                    updated_after=int(timestamp *
                                      1000) if timestamp > 0 else None)
                self.logger.info("Got %s issues in project %s", len(issues),
                                 project['youtrack_id'])
                current += limit
                issues_tasks = list(
                    self.check_issue(issue, timestamp * 1000)
                    for issue in issues)
                if issues_tasks:
                    await asyncio.wait(issues_tasks)
                if len(issues) < limit:
                    break
        except ssl.SSLError:
            self.logger.exception('SSLError')
            return
        except youtrack.YouTrackException as ex:
            self.logger.exception('Youtrack exception')
            return

    async def check_for_updates(self, interval):
        """
        Iterates over projects looking for updated issues
        """
        self.logger.info("Checking projects for updates")
        try:
            async with self.db_pool.acquire() as conn:
                tasks = []
                for project in await db.get_projects(conn):
                    tasks.append(self.check_project(project))
                await asyncio.wait(tasks)
        except asyncio.CancelledError:
            self.logger.info("cancelled")
        self.logger.info("Done")
Пример #8
0
#!/usr/bin/env python3
from aiotg import Bot, Chat

from config import TG_TOKEN

bot = Bot(api_token=TG_TOKEN)


@bot.command(r"ping")
def ping(chat: Chat, match):
    return chat.reply('pong')


if __name__ == "__main__":
    bot.run()
Пример #9
0
class CamBot:
    def __init__(self, agent: 'gphotos.GooglePhotosManager',
                 manager: vkmanager.VKManager):
        self._bot = Bot(conf.bot_token, proxy=conf.tele_proxy)
        self.session = self._bot.session
        self.loop = self._bot.loop
        self.menu_markup = Menu()
        self.init_handlers()
        self.agent = agent
        self.vk_manager = manager

    def init_handlers(self):
        self._bot.add_command(r'/mov (.+) (.+)', self.mov)
        self._bot.add_command(r'/push_vk (.+) (.+)', self.push_vk)
        self._bot.add_command(r'/check (.+) (.+)', self.check_album)
        self._bot.add_command(r'/full_check (.+)', self.full_check)
        self._bot.add_command(r'/clear (.+)', self.clear_command)
        self._bot.add_command(r'/reg', reg)
        self._bot.add_command(r'/ch', self.reg_channel)
        self._bot.add_command(r'/photo_reg', self.reg_photo_channel)
        self._bot.add_command(r'/menu', self.menu)
        self._bot.add_command(r'/all', self.img_all_cams)
        self._bot.add_command(r'/stats (.+)', self.stats_command)
        self._bot.add_command(r'/stats', self.stats_command)
        self._bot.add_command(r'/lstats (.+)', self.lstats_command)
        self._bot.add_command(r'/lstats', self.lstats_command)
        self._bot.add_command(r'/dbdata', self.db_data)
        self._bot.add_command(r'/daily', self.daily_movie_group_command)
        self._bot.add_command(r'/push_on', self.push_vk_on)
        self._bot.add_command(r'/push_off', self.push_vk_off)
        self._bot.add_callback(r'regular (.+)', regular)
        self._bot.add_callback(r'today (.+)', today)
        self._bot.add_callback(r'weekly (.+)', weekly)
        self._bot.add_callback(r'select (.+)', self.select)
        self._bot.add_callback(r'back', self.back)
        self._bot.add_callback(r'img (.+)', self.img_callback)
        self._bot.add_callback(r'choose_cam (.+)', self.choose_cam_callback)
        self._bot.add_callback(r'choose_photo_cam (.+)',
                               self.choose_photo_cam_callback)
        self._bot.add_callback(r'sync (.+)', self.sync_gphotos)
        self._bot.add_callback(r'gsnc (.+)', self.run_sync_gphotos)
        self._bot.add_callback(r'remove (.+)', self.remove_folder)
        self._bot.add_callback(r'post (.+) (.+)', self.post_photo)
        self._bot.add_callback(r'clear_cb (.+)', self.clear_callback)
        self._bot.add_callback(r'check_cb (.+)', self.full_check_callback)
        self._bot.callback(unhandled_callbacks)

    def stop(self):
        self._bot.stop()

    @ThreadSwitcherWithDB.optimized
    async def daily_stats(self):
        await self.stats_request(pendulum.yesterday(), self.notify_admins)

    @ThreadSwitcherWithDB.optimized
    async def daily_movie(self, cam: Cam):
        day = datetime.datetime.now() - datetime.timedelta(days=1)
        day = day.strftime('%d_%m_%Y')
        loop = asyncio.get_event_loop()
        with concurrent.futures.ThreadPoolExecutor() as pool:
            try:
                clip = await loop.run_in_executor(pool,
                                                  lambda: make_movie(cam, day))
            except FileNotFoundError as exc:
                logger.exception(exc)
                await self.notify_admins(
                    f'File {exc.filename} not found for daily movie {cam.name}: {day}'
                )
                return
            except Exception as exc:
                logger.exception(exc)
                await self.notify_admins(
                    f'Error during making daily movie for {cam.name}: {day}')
                return
        if cam.update_channel:
            async with db_in_thread():
                channels = db.query(Channel).filter(
                    Channel.cam == cam.name).all()
            for channel in channels:
                await send_video(Chat(self._bot, channel.chat_id), clip)
        await self.notify_admins(f'Daily movie for {cam.name}: {day} ready!')
        for chat in await self.admin_chats():
            await send_video(Chat(self._bot, chat.chat_id), clip)

    async def push_vk(self, chat, match):
        cam = await get_cam(match.group(1), chat)
        if not cam:
            return
        day = match.group(2)
        path = Path(conf.root_dir
                    ) / 'data' / cam.name / 'regular' / 'clips' / f'{day}.mp4'
        if not path.exists():
            await chat.send_text('Movie file does not exist!')
            return
        try:
            await self.vk_manager.new_post(cam.name, str(path),
                                           day.replace('_', ' '),
                                           day.replace('_', '/'))
        except vkmanager.VKManagerError as exc:
            logger.exception('Error during pushing video to vk')
            await chat.send_text(exc.detail)
        except Exception:
            logger.exception('Unhandled exception during pushing video to vk')
            await chat.send_text('Unhandled error!')
        await chat.send_text('Movie successfully published')

    async def mov(self, chat, match):
        """
        Make movie for specified cam and day. Example: /mov favcam 25_04_2019
        :param chat:
        :param match:
        :return:
        """
        cam = await get_cam(match.group(1), chat)
        if not cam:
            return
        day = match.group(2)
        loop = asyncio.get_event_loop()
        with concurrent.futures.ThreadPoolExecutor() as pool:
            try:
                clip = await loop.run_in_executor(pool,
                                                  lambda: make_movie(cam, day))
            except Exception:
                logger.exception('Error during movie request')
                await self.notify_admins(
                    f'Error during movie request {day} {cam.name}')
                return
        await self.notify_admins(f'Video ready. Uploading..')
        with open(clip.path, 'rb') as clip:
            await chat.send_video(clip)

    async def daily_movie_group(self):
        for cam in sorted(conf.cameras_list, key=lambda k: k.offset):
            if cam.render_daily:
                await self.daily_movie(cam)
        await self.daily_stats()

    async def daily_photo_group(self):
        for cam in conf.cameras_list:
            image = await CamHandler(cam,
                                     self._bot.session).get_img(regular=False)
            if not image:
                await self.notify_admins(
                    f'Error during image request for {cam.name}')
                continue
            path = image.original_path if cam.resize else image.path
            await self._post_photo(cam, path)

    async def daily_movie_group_command(self, chat, match):
        logger.info('Forced daily movie group command')
        await self.daily_movie_group()

    async def push_vk_on(self, chat: Chat, match):
        loop = asyncio.get_event_loop()
        cmd = f'systemctl --user start {conf.vk_service}'.split()
        try:
            await loop.run_in_executor(None, lambda: subprocess_call(cmd))
        except Exception:
            msg = 'Error during starting vk push service'
            logger.exception(msg)
            await chat.send_text(msg)
            return
        await chat.send_text('vk push service started')

    async def push_vk_off(self, chat: Chat, match):
        loop = asyncio.get_event_loop()
        cmd = f'systemctl --user stop {conf.vk_service}'.split()
        try:
            await loop.run_in_executor(None, lambda: subprocess_call(cmd))
        except Exception:
            msg = 'Error during stopping vk push service'
            logger.exception(msg)
            await chat.send_text(msg)
            return
        await chat.send_text('vk push service stopped')

    async def img_all_cams(self, chat: Chat, match):
        for cam in conf.cameras_list:
            await self.img_handler(chat, cam)

    async def img_handler(self, chat: Chat, cam):
        image = await CamHandler(cam, self._bot.session).get_img(regular=False)
        if not image:
            await chat.send_text(f'Error during image request for {cam.name}')
            return
        path = image.original_path if cam.resize else image.path
        markup = Markup([[
            InlineKeyboardButton(text='post',
                                 callback_data=f'post {cam.name} {path.name}')
        ]])
        with open(path, 'rb') as image:
            await chat.send_photo(image, reply_markup=markup.to_json())

    async def img_callback(self, chat, cq, match):
        await cq.answer()
        cam = await get_cam(match.group(1), chat)
        if not cam:
            return
        await self.img_handler(chat, cam)

    @ThreadSwitcherWithDB.optimized
    async def reg_channel(self, chat: Chat, match):
        async with db_in_thread():
            channel = db.query(Channel).filter(
                Channel.chat_id == chat.id).one_or_none()
        if channel:
            await self.notify_admins(f'Channel {chat.id} already registered!')
            return
        await chat.send_text('Choose cam for channel',
                             reply_markup=CamerasChannel().options.to_json())

    @ThreadSwitcherWithDB.optimized
    async def reg_photo_channel(self, chat: Chat, match):
        async with db_in_thread():
            channel = db.query(PhotoChannel).filter(
                PhotoChannel.chat_id == chat.id).one_or_none()
        if channel:
            await self.notify_admins(f'Channel {chat.id} already registered!')
            return
        await chat.send_text(
            'Choose cam for photo channel',
            reply_markup=CamerasChannel('choose_photo_cam').options.to_json())

    @ThreadSwitcherWithDB.optimized
    async def choose_cam_callback(self, chat, cq, match):
        cam = match.group(1)
        async with db_in_thread():
            channel = Channel(chat_id=chat.id, cam=cam)
            db.add(channel)
            db.commit()
        await cq.answer(text=f'Added channel for {cam}')
        await self.notify_admins(text=f'Added channel {chat.id} for {cam}')

    @ThreadSwitcherWithDB.optimized
    async def choose_photo_cam_callback(self, chat, cq, match):
        cam = match.group(1)
        async with db_in_thread():
            channel = PhotoChannel(chat_id=chat.id, cam=cam)
            db.add(channel)
            db.commit()
        await cq.answer(text=f'Added photo channel for {cam}')
        await self.notify_admins(
            text=f'Added photo channel {chat.id} for {cam}')

    async def post_photo(self, chat, cq, match):
        cam = match.group(1)
        photo = match.group(2)
        cam = conf.cameras[cam]
        path = Path(conf.root_dir) / 'data' / cam.name / 'imgs'
        if cam.resize:
            path /= 'original'
        path = path / '_'.join(photo.split('_')[:3]) / photo
        await self._post_photo(cam, path)
        await cq.answer()

    @ThreadSwitcherWithDB.optimized
    async def _post_photo(self, cam: Cam, photo: Path):
        async with db_in_thread():
            channels = db.query(PhotoChannel).filter(
                PhotoChannel.cam == cam.name).all()
        for channel in channels:
            chat = Chat(self._bot, channel.chat_id)
            with open(photo, 'rb') as ph:
                await chat.send_photo(ph)

    @ThreadSwitcherWithDB.optimized
    async def notify_admins(self, text, **options):
        async with db_in_thread():
            admins = db.query(Admin).all()
        for admin in admins:
            await self._bot.send_message(admin.chat_id, text, **options)

    @ThreadSwitcherWithDB.optimized
    async def admin_chats(self):
        async with db_in_thread():
            return db.query(Admin).all()

    async def menu(self, chat, match):
        await chat.send_text('Menu',
                             reply_markup=self.menu_markup.main_menu.to_json())

    async def select(self, chat: Chat, cq, match):
        await cq.answer()
        cam = match.group(1)
        await chat.edit_text(cq.src['message']['message_id'],
                             f'Camera: {cam}',
                             markup=dataclasses.asdict(
                                 self.menu_markup.cam_options[cam].markup))

    async def back(self, chat, cq, match):
        await cq.answer()
        await chat.edit_text(cq.src['message']['message_id'],
                             'Menu',
                             markup=dataclasses.asdict(
                                 self.menu_markup.main_menu))

    async def sync_gphotos(self, chat, cq, match):
        await cq.answer()
        cam = match.group(1)
        await chat.edit_text(cq.src['message']['message_id'],
                             f'Choose folder for {cam}',
                             markup=dataclasses.asdict(
                                 SyncFolders(cam).folders))

    async def run_sync_gphotos(self, chat, cq, match):
        _folder = match.group(1)
        folder = Path(conf.root_dir) / 'data' / _folder
        logger.debug(f'GOING TO SYNC FOLDER {folder}')
        await cq.answer(text=f'GOING TO SYNC FOLDER {folder}')
        await self.notify_admins(f'Started sync {folder}')
        try:
            await GooglePhotosManager().batch_upload(Path(folder))
        except Exception:
            logger.exception('Sync error!')
            await self.notify_admins(f'Error with {folder}!')
            return
        await self.notify_admins(f'{folder} successfully uploaded!')
        markup = Markup([[
            InlineKeyboardButton(text=f'{_folder}',
                                 callback_data=f'remove {_folder}')
        ]])
        await chat.send_text(f'Remove folder {folder.name}',
                             reply_markup=markup.to_json())

    async def remove_folder(self, chat, cq, match):
        await cq.answer(text='Removing folder..')
        folder = match.group(1)
        folder = Path(conf.root_dir) / 'data' / folder
        shutil.rmtree(folder)
        await chat.send_text('Successfully removed!')

    async def stats_command(self, chat: Chat, match):
        try:
            day = pendulum.from_format(match.group(1), 'DD_MM_YYYY')
        except IndexError:
            day = pendulum.today()
        await self.stats_request(day, chat.send_text)

    async def lstats_command(self, chat: Chat, match):
        try:
            day = pendulum.from_format(match.group(1), 'DD_MM_YYYY')
        except IndexError:
            day = pendulum.today()
        await self.stats_request(day, chat.send_text)

    @ThreadSwitcherWithDB.optimized
    async def db_data(self, chat: Chat, match):
        async with db_in_thread():
            md_data = db_data()
        await chat.send_text('\n'.join(md_data), parse_mode='Markdown')

    async def stats_request(self, day: pendulum.DateTime, send_command):
        logger.info(f'Getting stats info for {day}')
        try:
            markdown_result = await self.local_stats_handler(day)
        except Exception:
            logger.exception('Error during stats request')
            await send_command('Error during request stats')
            return
        day = day.format('DD_MM_YYYY')
        markup = Markup([[
            InlineKeyboardButton(text='check', callback_data=f'check_cb {day}')
        ], [
            InlineKeyboardButton(text='clear', callback_data=f'clear_cb {day}')
        ]])
        await send_command('\n'.join(markdown_result),
                           parse_mode='Markdown',
                           reply_markup=markup.to_json())

    async def stats_handler(self, day=None):
        loop = asyncio.get_event_loop()
        result = await loop.run_in_executor(None, lambda: stats(day))
        album_stats = await self.agent.album_stats(day)
        markdown_result = [f'#stats *{day.format("DD/MM/YYYY")}*']
        for d in result['cameras']:
            stat = result['cameras'][d]
            count, size = stat['count'], convert_size(stat['size'])
            if count:
                avg = convert_size(stat['size'] / count)
            else:
                avg = 0
            media_count = album_stats[d]
            markdown_result.append(
                f'*{d}*: {count} - {media_count} - {size} - {avg} ')
        total = convert_size(result['total'])
        markdown_result.append(f'*total*: {total}')
        free = convert_size(result['free'])
        markdown_result.append(f'*free*: {free}')
        return markdown_result

    async def local_stats_handler(self, day=None):
        loop = asyncio.get_event_loop()
        result = await loop.run_in_executor(None, lambda: stats(day))
        markdown_result = [f'#stats *{day.format("DD/MM/YYYY")}*']
        for d in result['cameras']:
            stat = result['cameras'][d]
            count, size = stat['count'], convert_size(stat['size'])
            if count:
                avg = convert_size(stat['size'] / count)
            else:
                avg = 0
            markdown_result.append(f'*{d}*: {count} - {size} - {avg} ')
        total = convert_size(result['total'])
        markdown_result.append(f'*total*: {total}')
        free = convert_size(result['free'])
        markdown_result.append(f'*free*: {free}')
        return markdown_result

    async def check_album(self, chat, match):
        cam = await get_cam(match.group(1), chat)
        if not cam:
            return
        day = match.group(2)
        await self.agent.check_album(cam, day)

    async def full_check_handler(self, chat, day):
        logger.info(f'Going to full check for {day}')
        for cam in conf.cameras_list:
            try:
                await self.agent.check_album(cam, day)
            except Exception:
                logger.exception(
                    f'Error during check and sync {cam.name} -- {day}')
                await chat.send_text(f'Error {cam.name} — {day}')
                continue
            await chat.send_text(f'Finished with {cam.name} — {day}')
        msg = f'Finished full check for {day}'
        logger.info(msg)
        await chat.send_text(msg)

    async def full_check(self, chat, match):
        day = match.group(1)
        await self.full_check_handler(chat, day)

    async def full_check_callback(self, chat, cq, match):
        day = match.group(1)
        await cq.answer(text=f'Running full check for {day}')
        await self.full_check_handler(chat, day)

    async def clear_handler(self, chat, day):
        logger.info(f'Going to clear for {day}')
        loop = asyncio.get_event_loop()
        for cam in conf.cameras_list:
            try:
                await loop.run_in_executor(None,
                                           lambda: clear_cam_storage(day, cam))
            except Exception:
                logger.exception(f'Error during clear {cam.name} -- {day}')
                await chat.send_text(f'Error {cam.name} — {day}')
                continue
            await chat.send_text(f'Finished with {cam.name} — {day}')
        logger.info(f'Finished clear for {day}')

    async def clear_command(self, chat, match):
        day = match.group(1)
        await self.clear_handler(chat, day)

    async def clear_callback(self, chat, cq, match):
        day = match.group(1)
        await cq.answer(text=f'Cleaning for {day}')
        await self.clear_handler(chat, day)
Пример #10
0
if len(sys.argv) < 2:
    print('usage: python simple.py simple.conf')
    sys.exit(1)
conf = sys.argv[1]
config = configparser.ConfigParser()
config.read(conf)
BOT_TOKEN = config.get('telegram', 'bot_token', fallback='')
ADMIN_ID = int(config.get('telegram', 'admin_id', fallback=0))
PROXY = config.get('telegram', 'proxy', fallback=None)
ADDRESS = config.get('ipc', 'address', fallback='http://127.0.0.1:1242/')
PASSWORD = config.get('ipc', 'password', fallback='')

logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger('simple_asf_bot')

bot = Bot(api_token=BOT_TOKEN, proxy=PROXY)


async def command(asf, cmd):
    return await asf.Api.Command.post(body={
        'Command': cmd
    })


async def main():
    async with IPC(ipc=ADDRESS, password=PASSWORD) as asf:
        @bot.command(r'^([^/].*)$')
        async def message(chat: Chat, match):
            sender = chat.sender['id']
            logger.info(f'Get {match.group(1)}')
            if sender == ADMIN_ID:
Пример #11
0
import json
import os
from aiotg import Bot

bot = Bot(api_token=os.environ["API_TOKEN"])


@bot.command(r'/start')
def start(chat, match):

    markup = {
        'type':
        'InlineKeyboardMarkup',
        'inline_keyboard': [
            [{
                'type': 'InlineKeyboardButton',
                'text': 'Button A',
                'callback_data': 'buttonclick-A'
            }, {
                'type': 'InlineKeyboardButton',
                'text': 'Button B',
                'callback_data': 'buttonclick-B'
            }],
            [{
                'type': 'InlineKeyboardButton',
                'text': 'Nohandle Button',
                'callback_data': 'no_callback_data'
            }],
        ]
    }
Пример #12
0
import textwrap
import random

# Bot
from aiotg import Bot

# Queries
from database.queries import user_exists, insert_user, deactivate_user
from database.queries import insert_text

# Variables
api_token = os.environ.get("API_TOKEN")
bot_name = os.environ.get("BOT_NAME")

# Bot
bot = Bot(api_token=api_token, name=bot_name)

# Logging
logger = logging.getLogger("bot")
logging.basicConfig(level=logging.DEBUG)


def format_text(text):
    return textwrap.dedent(text)


@bot.handle("new_chat_member")
async def new_chat_member_event(chat, member):
    logger.info("New chat member %s joined group", member["first_name"])
    text = format_text("""
    {greet}, {name}!
Пример #13
0
TOKEN = os.environ["PP_BOT_TOKEN"]
DB_PATH = os.environ.get("PP_BOT_DB_PATH",
                         os.path.expanduser("~/.tg_pp_bot.db"))
GREETING = """
Use 
/poker task url or description 
to start game.

Multiline is also supported
/poker line1
line2
Currently there is only one scale: 1, 2, 3, 5, 8, 13, 20, 40, ❔, ☕
"""

bot = Bot(TOKEN)
storage = GameRegistry()
init_logging()
REVEAL_RESTART_COMMANDS = [
    Game.OP_REVEAL, Game.OP_RESTART, Game.OP_RESTART_NEW, Game.OP_REVEAL_NEW
]


@bot.command("/start")
@bot.command("/?help")
async def start_poker(chat: Chat, match):
    await chat.send_text(GREETING)


@bot.command("(?s)/poker\s+(.+)$")
@bot.command("/(poker)$")
Пример #14
0
import logging

from aioredis import create_redis_pool, Redis
from aiotg import Chat, Bot

from trading_bot.manager import Manager, State
from trading_bot.settings import dev_hooks_token, chatbase_token, proxy_string
from trading_bot.sources.sources import SmartLab
from trading_bot.telegram_helper import keyboard_markup, build_menu

log = logging.getLogger(__name__)

bot = Bot(
    api_token=dev_hooks_token,
    chatbase_token=chatbase_token,
    name="TradingNewsBot",
    proxy=proxy_string,
)

manager = None


async def init(host):
    global manager

    redis: Redis = await create_redis_pool(host, minsize=5, maxsize=10)
    manager = Manager(redis=redis)

    async for chat_id, data in manager.check_new_all(save=False):
        pass
Пример #15
0
class TeleGate(object):
    def __init__(self):
        self.ids = PickleDict('ids')
        self.members = PickleDict('members')
        self.ignored = PickleDict('ignored')
        self.cooldown = defaultdict(lambda: 0)
        self.dialogs = {}
        self.tripmap = {}
        self.bot = Bot(api_token=config.token, default_in_groups=True)
        for content_type in ['photo', 'video', 'audio', 'voice', 'document', 'sticker']:
            self.bot.handle(content_type)(self.handle_chat)
        self.bot.default(self.handle_chat)
        # self.bot.command(r'/set(icon|name|region|cooldown) (.+)')(self.set_user_prefs)
        # self.bot.command('help')(self.help)
        self.bot.command('setup')(self.setup)
        self.bot.command('start')(self.setup)
        self.bot.callback(r"setup-(\w+)")(self.setup_button_clicked)

    async def get_trip_flags(self):
        async with self.bot.session.get(f'https://{config.url}/js/tripflags.js') as s:
            data = await s.text()
            for l in data.splitlines():
                if l.startswith('flags_hover_strings'):
                    self.tripmap[l.split('"')[1]] = l.split('"')[3]

    async def post(self, body, name="Anonymous", convo="General", trip="", file="", country=None):
        if trip:
            name = '{}#{}'.format(name, trip)
        data = {
            'chat': config.board,
            'name': name,
            'trip': trip or '',
            'body': body,
            'convo': convo,
        }
        if country:
            data['country'] = country
        if file:
            data['image'] = open(file, 'rb')
        await self.bot.session.post(
                f'https://{config.url}/chat/{config.board}',
                data=data, cookies={'password_livechan': config.password_livechan}
            )

    async def get_posts(self, last_count=0, limit=30):
        params = {'count': last_count, 'limit': limit}
        async with self.bot.session.get(f'https://{config.url}/last/{config.board}', params=params) as s:
            data = await s.json()
            data.reverse()
            return data

    def send_gif(self, chat, animation, caption="", **options):
        return self.bot.api_call(
            "sendAnimation",
            chat_id=str(chat.id),
            animation=animation,
            caption=caption,
            **options
        )

    def get_member(self, chat):
        default = Member(chat.message['from']['first_name'], config.default_trip, None, config.default_cooldown)
        return Member(*self.members.get(chat.message['from']['id'], default))

    async def updater(self):
        last_count = 0
        post_data = {'count': 0}
        while True:
            try:
                await asyncio.sleep(config.poll_interval)
                group = self.bot.group(config.group_id)
                data = await self.get_posts(last_count)
                for post_data in data:
                    if post_data['identifier'] in self.ignored:
                        continue
                    if post_data['convo'] == 'General' and post_data['count'] not in self.ids:
                        res = None
                        country2 = emoji_flags.get_flag(post_data['country'].split('-')[0])
                        if '-' in post_data['country']:
                            country2 = '{}-{}'.format(country2, post_data['country'].split('-')[1])
                        body = '{} {} {} {}:\n{}'.format(post_data['count'], post_data['name'],
                                                         self.tripmap.get(post_data.get('trip'), ''), country2,
                                                         post_data['body'])
                        image = post_data.get('image')
                        reply_to = self.ids.get(int(post_data['body'].lstrip('>').split()[0]) if post_data['body'].startswith('>>') else None)
                        reply_to = {'reply_to_message_id':str(reply_to)} if reply_to else {}
                        if image:
                            image = 'https://{}{}'.format(config.url, image.split('public', 1)[1])
                            filename = image.split('/')[-1]
                            body = body[:1024]
                            async with self.bot.session.get(image) as f:
                                if f.status == 200:
                                    data = await f.read()
                                    with open('tmp/{}'.format(filename), 'wb') as f:
                                        f.write(data)
                                else:
                                    data = None
                            if data:
                                with open('tmp/{}'.format(filename), 'rb') as f:
                                    ext = os.path.splitext(image)[1]
                                    if ext in ['.png', '.jpg']:
                                        res = await group.send_photo(f, caption=body, **reply_to)
                                    elif ext in ['.gif']:
                                        res = await self.send_gif(group, f, caption=body, **reply_to)

                                    elif ext in ['.mp4']:
                                        res = await group.send_video(f, caption=body, **reply_to)
                                    elif ext in ['.mp3', '.ogg']:
                                        res = await group.send_audio(f, caption=body)
                                    elif ext == '.webm':
                                        body += f'\nhttps://{config.url}/tmp/uploads/' + filename
                                        res = await group.send_text(body, **reply_to)
                                os.unlink('tmp/{}'.format(filename))
                            else:
                                res = await group.send_text(body, **reply_to)
                        elif post_data['body']:
                            res = await group.send_text(body, **reply_to)

                        for st in re.findall(r'\[st\]([\w\d\-\.]+)\[\/st\]', body):
                            path = 'stickers/{}.png'.format(st)
                            if not os.path.exists(path):
                                async with self.bot.session.get(f'https://{config.url}/images/stickers/{st}.png') as f:
                                    if f.status == 200:
                                        data = await f.read()
                                        with open(path, 'wb') as f:
                                            f.write(data)
                                        with open(path, 'rb') as f:
                                            res2 = await group.send_photo(f)
                                            if not res:
                                                res = res2
                        if res:
                            self.ids[post_data['count']] = res['result']['message_id']
                            self.ids[res['result']['message_id']] = post_data['count']
            except Exception as e:
                traceback.print_exc()
            last_count = post_data['count']

    async def handle_chat(self, chat, image):
        if not chat.is_group():
            if chat.message['from']['id'] in self.dialogs:
                await self.setup(chat, image)
            return
        else:
            if chat.message['from']['id'] not in self.members:
                await self.setup(chat, image)
        if type(image) == list:
            image = image[-1]
        if 'file_id' in image:
            cq = chat.message
            text = chat.message.get('caption', '')
        else:
            cq = image
            text = cq['text']
        if 'reply_to_message' in cq:
            id = cq['reply_to_message']['message_id']
            if id in self.ids:
                text = '>>{}\n{}'.format(self.ids[id], text)
        id = image.get('file_id')
        if id:
            info = await self.bot.get_file(id)

            path = 'tmp/{}'.format(info['file_path'].split('/')[-1])
            if path.endswith('.oga'): path = path.replace('.oga', '.ogg')
            async with self.bot.download_file(info['file_path']) as res:
                data = await res.read()
                open(path, 'wb').write(data)
            if path.endswith('.webp'):
                newpath = path.replace('.webp', '.png')
                os.system('convert {} {}'.format(path, newpath)) # requires imagemagick
                path = newpath
            elif path.endswith('.tgs'):
                newpath = 'stickers/{}.gif'.format(image['file_id'])
                if not os.path.exists(newpath):
                    import tgs
                    from tgs.exporters import gif
                    a=tgs.parsers.tgs.parse_tgs(path)

                    with open(newpath, 'wb') as f:
                        gif.export_gif(a, f)
                os.unlink(path)
                path = newpath
        else:
            path = None
        member = self.get_member(chat)
        if not (time() > self.cooldown[cq['from']['id']] + member.cooldown_limit):
            return
        self.cooldown[cq['from']['id']] = time()
        await self.post(text, name=member.name, trip=member.trip, country=member.country, file=path)
        if path and path.startswith('tmp/'):
            os.unlink(path)
        await chat.delete_message(cq['message_id'])

    async def setup(self, chat, match):
        member = self.get_member(chat)
        id = chat.message['from']['id']
        if chat.is_group():
            chat = self.bot.private(chat.message['from']['id'])
        if id in self.dialogs:
            setattr(member, {'name': 'name', 'icon': 'trip', 'region': 'country'}[self.dialogs[id]], chat.message['text'])
            if member.trip == 'none':
                member.trip = None
            self.members[chat.message['from']['id']] = member
            del self.dialogs[id]

        buttons = []
        for button in ['name', 'icon', 'region']:
            buttons.append({
                "type": "InlineKeyboardButton",
                "text": "Set {}".format(button),
                "callback_data": "setup-{}".format(button),
            })
        markup = {
            "type": "InlineKeyboardMarkup",
            "inline_keyboard": [buttons]
        }
        chat.send_text(f"Name: {member.name}\nIcon: {member.trip}\nRegion: {member.country}", reply_markup=json.dumps(markup))

    def setup_button_clicked(self, chat, cq, match):
        if chat.is_group():
            chat = self.bot.private(chat.message['from']['id'])
        id = chat.message['chat']['id']
        param = match.group(1)
        self.dialogs[id] = param
        example = {
            'name': 'Kot',
            'icon': 'plkot; none for no icon',
            'region': 'PL-77 or RU-47',
        }[param]
        chat.send_text('Send your {}(for example: {})'.format(param, example))

    def run(self):
        loop = asyncio.get_event_loop()
        loop.create_task(self.updater())
        loop.create_task(self.get_trip_flags())
        self.bot.run()
Пример #16
0
import os
import asyncio
from aiohttp import web
from aiotg import Bot, Chat, InlineQuery, CallbackQuery
from klocmod import LocalizationsContainer

import msgdb
import strconv
from txtproc import TextProcessorsLoader, TextProcessor
from txtprocutil import resolve_text_processor_name
from data.config import *
from queryutil import *

DECRYPT_BUTTON_CACHE_TIME = 3600  # in seconds

bot = Bot(api_token=TOKEN, default_in_groups=True)
localizations = LocalizationsContainer.from_file("app/localizations.ini")
text_processors = TextProcessorsLoader(strconv)


@bot.command("/start")
@bot.command("/help")
@bot.default
async def start(chat: Chat, _) -> None:
    lang = localizations.get_lang(chat.message['from'].get('language_code'))
    await chat.send_text(lang['help_message'])
    await chat.send_text(lang['help_message_transformers_list'])
    for processor in text_processors.all_processors:
        help_message_key = 'help_' + processor.snake_case_name
        localized_help_message = lang[help_message_key]
        # skip empty and undefined help messages
Пример #17
0
# Photos
from commands.photos import insert_watermark
# from commands.photos import process_photo

# Contacts
from commands.contacts import process_contact

# Inline queries
from commands.inline import process_inline_query

# Variables
api_token = os.environ.get('API_TOKEN')
bot_name = os.environ.get('BOT_NAME')

# Bot
bot = Bot(api_token=api_token, name=bot_name)

# Channel
channel = bot.channel(os.environ.get('CHANNEL_NAME', '@VodiyBozorTest'))

# Logging
logger = logging.getLogger('bot')
logging.basicConfig(level=logging.DEBUG)


@bot.command(r'/start')
@bot.command(r'/on')
async def start(chat, match):
    await process_start_command(chat, match, logger)
    await process_ads_command(chat, match, logger)
Пример #18
0
import time
from concurrent.futures import ThreadPoolExecutor
from aiotg import Bot

formatter = logging.Formatter('[%(levelname)s] %(message)s (%(asctime)s)')
file_handler = logging.FileHandler('torrent-helper.log')
stdout_handler = logging.StreamHandler(sys.stdout)
file_handler.setFormatter(formatter)
stdout_handler.setFormatter(formatter)

logger = logging.getLogger('torrent-helper')
logger.addHandler(file_handler)
logger.addHandler(stdout_handler)
logger.setLevel(logging.INFO)

t2m_bot = Bot(api_token='')
m2t_bot = Bot(api_token='')

proc_pool = ThreadPoolExecutor(15)


@t2m_bot.command(r'/(start|help)')
async def start(chat, match):
    await chat.send_text('Send torrent file here')


@m2t_bot.command(r'/(start|help)')
async def start(chat, match):
    await chat.send_text('Send magnet link here')

Пример #19
0
```棒棒勝 type:mp3```
```棒棒勝 type:mpeg```
若同時想搜尋作者和曲名,請用 `>` 隔開 (預設為作者、曲名都納入搜尋),像這樣:
```棒棒勝>洨安之歌```
也可以搭配`type`指令,像這樣:
```棒棒勝>洨安之歌 type:flac```
輸入 `/stats` 來獲取 bot 資訊。
用 `/music` 指令來在群聊內使用棒棒勝 Music Bot,像這樣:
```/music 棒棒勝```
"""

not_found = """
找不到資料 :/
"""
bot = Bot(api_token=os.environ.get('API_TOKEN'),
          name=os.environ.get('BOT_NAME'),
          botan_token=os.environ.get("BOTAN_TOKEN"))

logger = logging.getLogger("musicbot")
channel = bot.channel(os.environ.get('CHANNEL'))


@bot.handle("audio")
async def add_track(chat, audio):
    if (str(chat.sender) == 'N/A'):
        sendervar = os.environ.get('CHANNEL_NAME')
    else:
        sendervar = str(chat.sender)
    if (await db.tracks.find_one({"file_id": audio["file_id"]})):
        await chat.send_text("資料庫裡已經有這首囉 owo")
        logger.info("%s 傳送了重複的歌曲 %s %s", sendervar,
Пример #20
0
 def __init__(self, config=None, *, context=None, loop=None):
     super().__init__(config, context=context, loop=loop)
     self.bot = Bot(api_token=self.config.api_token)
Пример #21
0
import os
import logging

from aiotg import Bot, Chat
from onvotar import calculate

bot = Bot(
    api_token=os.environ.get("API_TOKEN"),
    name=os.environ.get("BOT_NAME"),
)

AJUT_CAT = ('Per conèixer el teu col·legi electoral, '
            'envia un missatge /vota amb les teves dades '
            'separades per espais i '
            'fent servir aquest format: \n'
            '/vota DNI DATA_NAIXEMENT CODI_POSTAL\n\n'
            'Exemple:\n/vota 00001714N 01/10/2017 01234')

AJUT_CAST = ('Para conocer tu colegio electoral, '
             'envía un mensaje /votar con tus datos '
             'separados por espacios y '
             'usando este formato: \n'
             '/vota DNI DATA_NACIMIENTO CODIGO_POSTAL\n\n'
             'Ejemplo:\n/votar 00001714N 01/10/2017 01234')

AJUT_ENG = ('To know you voting booth location, '
            'send a message /vote with your data '
            'separated with spaces, using  '
            'this format: \n'
            '/vote DNI BIRTH_DATE ZIP_CODE\n\n'
            'Example:\n/vote 00001714N 01/10/2017 01234')
Пример #22
0
import os
from aiotg import Bot, Chat

bot = Bot(api_token="API_TOKEN")


@bot.command(r"bitcoin")
async def bitcoin(chat: Chat, match):
    url = "https://api.bitcoinaverage.com/ticker/global/USD/"
    async with bot.session.get(url) as s:
        info = await s.json()
        await chat.send_text(info["24h_avg"])


if __name__ == "__main__":
    bot.run(debug=True)
Пример #23
0
import json
import os
import datetime
import asyncio

from aiotg import Bot, Chat
from rzd.aiorzd import RzdFetcher, UpstreamError
from rzd.config import QUERY_REGEXP_LIST
from rzd.helper import logger, QueryString, NotifyExceptions

os.environ.setdefault('BOT_CONFIG', 'rzd/config.json')

with open(os.environ['BOT_CONFIG']) as cfg:
    config = json.load(cfg)

bot = Bot(config['API_TOKEN'], name=config['BOT_NAME'])


def multibot(command, default=False):
    def decorator(fn):
        for r in QUERY_REGEXP_LIST:
            fn = bot.command(r'/%s@%s\s+%s' % (command, bot.name, r))(fn)
            fn = bot.command(r'/%s\s+%s' % (command, r))(fn)
            if default:
                fn = bot.command(r'@%s\s+%s' % (bot.name, r))(fn)

        return fn

    return decorator

Пример #24
0
import os

from aiotg import Bot, Chat
from telegram import ReplyKeyboardMarkup, KeyboardButton

from photo import make_photo

logging.basicConfig(
    level=getattr(logging, os.environ.get("BOT_LOGGING_LEVEL", "DEBUG")),
    format="%(asctime)s | %(name)s | %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)
ch = logging.StreamHandler()
logger.addHandler(ch)

bot = Bot(api_token=os.environ["BOT_TOKEN"], )


def get_admins():
    return map(int, os.environ.get("BOT_ADMINS", "").split(","))


def is_authorized(sender):
    return sender["id"] in get_admins()


def get_button():
    return json.dumps(
        ReplyKeyboardMarkup(
            [[KeyboardButton(text="Photo")]],
            resize_keyboard=True,
Пример #25
0
        MATRIX_HOST_BARE = CONFIG['hosts']['bare']

        MATRIX_PREFIX = MATRIX_HOST + '_matrix/client/r0/'
        MATRIX_MEDIA_PREFIX = MATRIX_HOST + '_matrix/media/r0/'

        USER_ID_FORMAT = CONFIG['user_id_format']
        DATABASE_URL = CONFIG['db_url']

except (OSError, IOError) as exception:
    print('Error opening config file:')
    print(exception)
    exit(1)

GOO_GL_URL = 'https://www.googleapis.com/urlshortener/v1/url'

TG_BOT = Bot(api_token=TG_TOKEN)
MATRIX_SESS = ClientSession()
SHORTEN_SESS = ClientSession()


def create_response(code, obj):
    """
    Create an HTTP response with a JSON body.
    :param code: The status code of the response.
    :param obj: The object to serialize and include in the response.
    :return: A web.Response.
    """
    return web.Response(text=json.dumps(obj),
                        status=code,
                        content_type='application/json',
                        charset='utf-8')
Пример #26
0
import json
from aiotg import Bot, Chat, CallbackQuery
from util import format_message, match_category, \
    download_gifs, produce_imgs, log_users
from spider import fetch_lists, fetch_img

with open('token.json') as t, open('category.json') as c:
    token = json.loads(t.read())
    category = json.loads(c.read())

bot = Bot(**token)
root_url = "http://www.gamersky.com/ent/"
help_tetx = "点击按钮查看下一页, 或者点击原网址查看详细内容"


@bot.command(r"/start")
async def list_category(chat: Chat, match):
    kb, row = [], -1
    for idx, item in enumerate(category["name"]):
        if idx % 2 == 0:
            kb.append([])
            row += 1
        kb[row].append(item)
    keyboard = {
        "keyboard": kb,
        "resize_keyboard": True
    }
    text = "请选择你喜欢的图片类型,动态图和冷知识还有bug,其他类型都能正常查看"
    message = await chat.send_text(text=text, reply_markup=json.dumps(keyboard))
    await log_users(message)
Пример #27
0
import os
from aiotg import Bot, Chat

bot = Bot(os.environ["API_TOKEN"])


@bot.command(r"bitcoin")
async def bitcoin(chat: Chat, match):
    url = "https://api.bitcoinaverage.com/ticker/global/USD/"
    async with bot.session.get(url) as s:
        info = await s.json()
        await chat.send_text(info["24h_avg"])


if __name__ == '__main__':
    bot.run(debug=True)
Пример #28
0
import os

from aiotg import Bot, Chat
import imageio
from services import ClassifyModel, get_square

model = ClassifyModel()

bot = Bot(api_token=os.getenv("TG_TOKEN"))


@bot.command("/start")
async def start(chat: Chat, match):
    return chat.reply("Send me photo of ant or bee.")


@bot.handle("photo")
async def handle_photo(chat: Chat, photos):
    # Get image binary data
    meta = await bot.get_file(photos[-1]["file_id"])
    resp = await bot.download_file(meta["file_path"])
    data = await resp.read()

    # Convert binary data to numpy.ndarray image
    image = imageio.imread(data)

    # Do the magic
    tag = await model.predict.call(image)

    # Simple text response
    await chat.reply(f"I think this is {tag} ...")
Пример #29
0
from aiotg import Bot, Chat

from db import UserData

bot = Bot("518654004:AAGeHYTzXDd-gRN-2LwjUeljN4nghIM3F34")


async def greeter(private_id, body):
    private = bot.private(private_id)
    await private.send_text(body)


@bot.command(r"/whoami")
async def whoami(chat, match):
    return chat.reply(chat.sender["id"])


@bot.command(r"/create (.+)")
async def create_new_app(chat: Chat, match):
    private_id = chat.sender["id"]
    app_name = str(match.group(1))
    print(str(private_id) + " " + str(app_name))
    if UserData.select().where(UserData.app_name == app_name):
        return chat.reply("App with this name already exists")
    else:
        UserData.create(app_name=app_name, private_id=private_id).save()
        return chat.reply("App " + str(app_name) + " successfully create")


if __name__ == '__main__':
    bot.run(debug=True)
Пример #30
0
import os
from enum import Enum
from urllib.parse import quote

import sys
from aiotg import Bot, aiohttp

from utils import html_decode

bot = Bot(api_token=os.environ['BOT_TOKEN'])
advice_api_url = "http://f*****g-great-advice.ru/api/{}"
sound_url = 'http://f*****g-great-advice.ru/files/sounds/{}'  # sound_9.MP3
dummy_image = 'https://dummyimage.com/1000x200/000000/ffffff.png&text={}'


class Advice:
    def __init__(self, id, text, sound, stat=0):
        self._id = id
        self.text = html_decode(text)
        self.sound = sound
        self.stat = stat

    @property
    def sound_url(self):
        return sound_url.format(self.sound)

    @property
    def photo_url(self):
        return dummy_image.format(quote(self.text))

Пример #31
0
class TelegramAgent(Agent):
    def __init__(self, name=None):
        super().__init__(name=name)
        self._bot = Bot(api_token=TELEGRAM_BOT_API_TOKEN,
                        name=TELEGRAM_BOT_NAME,
                        api_timeout=10)
        self._bot.default(self.on_incoming_telegram_message)
        self.sent_telegram_messages = {}

    def on_incoming_telegram_message(self, chat, message):
        try:
            text = message['text']
            name = text
            if len(name) > FRAME_NAME_MAX_LENGTH:
                name = name[:FRAME_NAME_MAX_LENGTH - 1] + '…'
            full_name = '{} {}'.format(message['from']['first_name'],
                                       message['from']['last_name'])
            sent_msg = self.message(name,
                                    data={
                                        'text': text,
                                        'message_id': message['message_id'],
                                        'chat_id': message['chat']['id'],
                                        'user_id': message['from']['id'],
                                        'username':
                                        message['from']['username'],
                                        'full_name': full_name,
                                        'session': message['chat']['id'],
                                    })
            self.sent_telegram_messages.update(
                {sent_msg.id: message['chat']['id']})
        except Exception:
            print(traceback.format_exc())
            print(message.name, message.data)

    @on_message('*')
    async def telegram_message_reply(self, message):
        if message.reply_to not in self.sent_telegram_messages:
            return
        text = message.data.text or message.name
        try:
            chat_id = self.sent_telegram_messages[message.reply_to]
            # del self.sent_telegram_messages[message.reply_to]
            await self._bot.send_message(chat_id=chat_id, text=text)
            self.emit('telegram_reply_sent',
                      data={
                          'text': text,
                          'chat_id': chat_id
                      })
        except Exception:
            print(traceback.format_exc())
            print(message.name, message.data)

    @on_event('send_telegram_message')
    async def send_message(self, event):
        text = event.data.text
        chat_id = event.data.session or event.data.chat_id
        if not chat_id:
            self.emit('telegram_message_error',
                      data={'text': 'session or chat_id expected.'})
            return
        try:
            ret_val = await self._bot.send_message(chat_id=chat_id, text=text)
            self.emit('telegram_message_sent',
                      data={
                          'text': text,
                          'chat_id': chat_id,
                          'return': ret_val
                      })
        except Exception:
            print(traceback.format_exc())
            print(event.name, event.data)

    @on_event('*** started')
    def on_started(self, event):
        self.emit('telegram_connecting')
        self.spawn(self._bot.loop())

    @on_event('*** stopping')
    def on_stopping(self, event):
        self._bot.stop()
Пример #32
0
import os
import asyncio
from aiotg import Bot

bot = Bot(os.environ["API_TOKEN"])
channel = bot.channel(os.environ["CHANNEL"])
private = bot.private(os.environ["PRIVATE"])


async def greeter():
    await channel.send_text("Hello from channel!")
    await private.send_text("Why not say hello directly?")

loop = asyncio.get_event_loop()
loop.run_until_complete(greeter())