Beispiel #1
0
    def __init__(self):
        self.helix_api = Helix(client_id=Settings().config['client_id'],
                               bearer_token=Arguments().oauth_token,
                               use_cache=False)

        self.formats: List[str] = []
        self.whitelist: List[str] = []
        self.blacklist: List[str] = []

        # Populate format list according to whitelist and blacklist
        if 'all' in Arguments().formats and 'all' in Settings(
        ).config['formats']:
            self.blacklist = Settings(
            ).config['formats']['all']['whitelist'] or []
            self.whitelist = Settings(
            ).config['formats']['all']['blacklist'] or []

            # Append formats to list if they can be used
            self.formats = [
                format_name
                for format_name in Settings().config['formats'].keys()
                if self._can_use_format(format_name)
            ]

        else:
            self.formats = [
                format_name for format_name in Arguments().formats
                if self._can_use_format(format_name)
            ]
Beispiel #2
0
def get_vod(vod: int, client: twitch.Helix):
    """
    Given a twitch Vod ID and Twitch API Client, return that video object and throw error if given an incorrect Vod iD
    :param vod: Twitch video ID , Twitch-Python Helix client
    :return: video: Twitch Helix API video object - twitch.helix.Video
    """

    # check if the video exists and is legitimate based on id
    try:
        video = client.video(video_id=vod)
    except requests.exceptions.HTTPError:
        sys.exit('Invalid VoD ID entered.')

    choice = input((f"Is '{video.title}' by {video.user_name} of duration {video.duration} created on {video.created_at} your requested VoD? (y/n)"))
    if choice.lower() == "y":
        return video
    else:
        sys.exit("Operation cancelled by user.")
Beispiel #3
0
import webbrowser
import os
from twitch import Helix
from subprocess import Popen
import tkinter
from tkinter import *

client = Helix(client_id='', bearer_token='')  #Need to grab twitch client ID
count = 20  #Change this number to change the amount of streamers the twitch API pulls
game_name = "warframe"
f = input("write game name : ")
while (len(f) > 0):
    if client.game(name=f) == None:
        f = input("wrong name write game name : ")
    else:
        game_name = f
        break
game = client.game(name=game_name).id
print(game)


def check_for_streams():
    global streams
    streams = client.streams(game_id=game, first=count).users


#credit to @jancodes for the idea


def multiTwitch(myList):
    Popen(
Beispiel #4
0
class Downloader:
    def __init__(self):
        self.helix_api = Helix(client_id=Settings().config['client_id'],
                               bearer_token=Arguments().oauth_token,
                               use_cache=False)

        self.formats: List[str] = []
        self.whitelist: List[str] = []
        self.blacklist: List[str] = []

        # Populate format list according to whitelist and blacklist
        if 'all' in Arguments().formats and 'all' in Settings(
        ).config['formats']:
            self.blacklist = Settings(
            ).config['formats']['all']['whitelist'] or []
            self.whitelist = Settings(
            ).config['formats']['all']['blacklist'] or []

            # Append formats to list if they can be used
            self.formats = [
                format_name
                for format_name in Settings().config['formats'].keys()
                if self._can_use_format(format_name)
            ]

        else:
            self.formats = [
                format_name for format_name in Arguments().formats
                if self._can_use_format(format_name)
            ]

    def _can_use_format(self, format_name: str) -> bool:
        """
        Check if format name should be used based on whitelist and blacklist
        :param format_name: Name of format
        :return: If format should be used
        """

        # Lowercase format name
        format_name = format_name.lower()

        # Reserved format names
        if format_name in ['all']:
            return False

        # Format does not exist
        if format_name not in Settings().config['formats'].keys():
            return False

        # Whitelisted formats
        if self.whitelist and format_name not in self.whitelist:
            return False

        # Blacklisted formats
        if self.blacklist and format_name in self.blacklist:
            return False

        return True

    def video(self, video: Video) -> None:
        """
        Download chat from video
        :param video: Video object
        :return: None
        """

        # Parse video duration
        regex = re.compile(
            r'((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')
        parts = regex.match(video.duration).groupdict()

        time_params = {}
        for name, param in parts.items():
            if param:
                time_params[name] = int(param)

        video_duration = datetime.timedelta(**time_params)

        formatter = Formatter(video)

        # Special case for JSON
        # Build JSON object before writing it
        if 'json' in self.formats:
            Logger().log('Downloading JSON data', Log.VERBOSE)
            output: str = Pipe(
                Settings().config['formats']['json']['output']).output(
                    video.data)
            os.makedirs(os.path.dirname(output), exist_ok=True)

            with open(output + ".tmp", 'w', encoding='utf-8') as file:
                file.write("{\n")
                file.write("\"video\": ")
                file.write(json.dumps(video.data, indent=4))
                file.write(",\n")
                file.write("\"comments\": [\n")
                comment = None
                for comment in video.comments:
                    # Skip unspecified users if a list is provided.
                    if Arguments().users and comment.commenter.name.lower(
                    ) not in Arguments().users:
                        continue

                    # If specified, only include messages that include a specified string
                    if Arguments().includes and Arguments(
                    ).includes not in comment.message.body.lower():
                        continue

                    file.write(json.dumps(comment.data, indent=4))
                    file.write(",\n")

                    # Ignore comments that were posted after the VOD finished
                    if Settings().config['formats']['json'].get(
                            'comments', {}).get('ignore_new_comments', False):
                        comment_date = dateutil.parser.parse(
                            comment.created_at)
                        vod_finish_date = dateutil.parser.parse(
                            video.created_at) + video_duration

                        if comment_date > vod_finish_date:
                            continue

                    if Logger().should_print_type(Log.PROGRESS):
                        self.draw_progress(
                            current=comment.content_offset_seconds,
                            end=video_duration.seconds,
                            description='json')
                if comment:
                    file.seek(file.tell() - 2)
                file.write("\n]\n")
                file.write("}\n")
            os.rename(output + ".tmp", output)
            Logger().log(f'[json] {output}')

        # For each format (ignore json this time)
        for format_name in [x for x in self.formats if x not in ['json']]:
            Logger().log(f'Formatting chat using: {format_name}', Log.VERBOSE)

            # Get (formatted_comment, comment), output
            comment_tuple, output = formatter.use(format_name)

            # Create output directory and write to file
            os.makedirs(os.path.dirname(output), exist_ok=True)
            with open(output, '+w', encoding='utf-8') as file:

                # For every comment in video
                for formatted_comment, comment in comment_tuple:

                    # Skip unspecified users if a list is provided.
                    if Arguments().users and comment.commenter.name.lower(
                    ) not in Arguments().users:
                        continue

                    # If specified, only include messages that include a specified string
                    if Arguments().includes and Arguments().includes.lower(
                    ) not in comment.message.body.lower():
                        continue

                    # Ignore comments that were posted after the VOD finished
                    if Settings().config['formats'][format_name].get(
                            'comments', {}).get('ignore_new_comments', False):
                        comment_date = dateutil.parser.parse(
                            comment.created_at)
                        vod_finish_date = dateutil.parser.parse(
                            video.created_at) + video_duration

                        if comment_date > vod_finish_date:
                            continue

                    # Draw progress
                    if comment and Logger().should_print_type(Log.PROGRESS):
                        self.draw_progress(
                            current=comment.content_offset_seconds,
                            end=video_duration.seconds,
                            description=format_name)

                    # Display preview
                    Logger().log(formatted_comment, Log.PREVIEW)

                    # Write comment to file
                    file.write('{}\n'.format(formatted_comment))

            Logger().log('[{}] {}'.format(format_name, output))

    def videos(self, video_ids: List[int]) -> None:
        """
        Download multiple video ids
        :param video_ids: List of video ids
        :return: None
        """
        for video in self.helix_api.videos(video_ids):
            Logger().log(format('\n{}'.format(video.title)), Log.REGULAR)
            self.video(video)

    def channels(self, channels: List[str]) -> None:
        """
        Download videos from multiple channels
        :param channels: List of channel names
        :return: None
        """
        for channel, videos in self.helix_api.users(channels).videos(
                first=Arguments().first):
            Logger().log(format('\n{}'.format(channel.display_name)),
                         Log.REGULAR)
            for video in videos:
                Logger().log(format('\n{}'.format(video.title)), Log.REGULAR)
                self.video(video)

    @staticmethod
    def draw_progress(current: float,
                      end: float,
                      description: str = 'Downloading') -> None:
        """
        Draw download progress
        :param current: Current chat position (seconds)
        :param end: End position (seconds)
        :param description: Progress description
        :return:
        """
        sys.stdout.write('[{}] {}%\r'.format(
            description, '%.2f' % min(current * 10 / end * 10, 100.00)))
        sys.stdout.flush()
Beispiel #5
0
 def __init__(self, clientID: str, bearer_token: str) -> None:
     self.helixClient : Helix =  Helix(client_id=clientID, bearer_token=bearer_token, use_cache=False)
     self.commentData : Chat = Chat()
     self.commentAnalyzer : Analyzer = Analyzer()
     self.currentVideo : Video = None
Beispiel #6
0
def main():
    parser = argparse.ArgumentParser(description="Twitch notifications")
    parser.add_argument("-c",
                        "--channel",
                        default="#video",
                        help="Slack channel")
    parser.add_argument(
        "-n",
        "--notifications",
        default="#ci",
        help="Slack channel notifications for errors or warnings")
    parser.add_argument("-i",
                        "--interval",
                        default=30,
                        help="Update interval in seconds",
                        type=int)
    parser.add_argument("-u", "--users", default="", help="Twitch users")
    args = parser.parse_args()

    remember_online_users = []

    TWITCH_CLIENT_ID = os.environ["TWITCH_CLIENT_ID"]
    TWITCH_CLIENT_SECRET = os.environ["TWITCH_CLIENT_SECRET"]

    def bearer():
        global twitch_access_token_expires_in
        global twitch_access_token
        if (twitch_access_token_expires_in < (60 * 15)
                and not twitch_access_token):
            connection = http.client.HTTPSConnection("id.twitch.tv")
            connection.request(
                "POST", "/oauth2/token?client_id=" + TWITCH_CLIENT_ID +
                "&client_secret=" + TWITCH_CLIENT_SECRET +
                "&grant_type=client_credentials")
            response = json.loads(
                connection.getresponse().read().decode('utf8'))
            twitch_access_token = response['access_token']
            twitch_access_token_expires_in = int(response['expires_in'])
        return twitch_access_token

    while (True):
        twitch = Helix(client_id=TWITCH_CLIENT_ID,
                       client_secret=TWITCH_CLIENT_SECRET,
                       bearer_token=bearer())
        slack = WebClient(token=os.environ["SLACK_API_KEY"])
        try:
            for user in args.users.split(","):
                if twitch.user(user).is_live:
                    print("TWITCH_LIVE: {}".format(user))
                    if user not in remember_online_users:
                        remember_online_users.append(user)
                        slack.chat_postMessage(
                            channel=args.channel,
                            attachments=[{
                                "text":
                                "TWITCH_LIVE: https://www.twitch.tv/{}".format(
                                    user),
                                "color":
                                "#ff0000"
                            }])
                else:
                    if user in remember_online_users:
                        remember_online_users.remove(user)
        except Exception as exception:
            print(exception)
            slack.chat_postMessage(
                channel=args.notifications,
                attachments=[{
                    "text":
                    "ERROR: reevefresh: Failed to fetch Twitch users status",
                    "color": "#ff0000"
                }])
        print("Online users: {}\n".format(",".join(remember_online_users)))
        time.sleep(args.interval)
TODO:
    -add emoji support for exporting data to files
    -allow users to get VODs from specific timeframes
    -allow users to search for messages from specific users
    -integrate this into a webapp to host on the website
    -make this into a class?
    -bugfixing
'''

from twitch import Helix
import re, time, argparse
import cfg

# --- API key ---
helix = Helix(client_id=cfg.CLIENT_ID,
              bearer_token=cfg.BEARER_TOKEN,
              use_cache=True)

# --- Argument parser ---
parser = argparse.ArgumentParser(description="View VOD comments and search through them.")
parser.add_argument("-u", "--user", help="desired user to view")
parser.add_argument("-c", "--count", help="number of most recent vods to view", type=int, default=1)
parser.add_argument("-s", "--search", help="term to search for in vods")
parser.add_argument("-t", "--realtime", help="include real-world time comments were posted at", action="store_true")
args = parser.parse_args()

# --- Main stuff ---
user = helix.user(args.user if args.user else input('User: '******'Number of VODs to search: '))
vods = user.videos(first=vodCount)
searchTerm = args.search if args.search else input('Search for: ')
Beispiel #8
0
 def __acquire_authorized_api(self) -> Helix:
     self.__bearer_token = self.__acquire_token()
     self.__api = Helix(client_id=self.__client_id,
                        client_secret=self.__client_secret,
                        bearer_token=f'bearer {self.__bearer_token}')
     return self.__api
Beispiel #9
0
 def __get_user(self, api: Helix, nick_or_id: Union[str, int]) -> Optional[User]:
     return api.user(nick_or_id)
Beispiel #10
0
# stdlib
from importlib import import_module
from os import O_PATH
from rx.core.typing import Observer
# 3rd party
from twitch import Chat, Helix
from twitch.chat import Message
# local
from .. import config
from ..web import app
from .commands import *

message_handlers = []

# Twitch API client
helix = Helix(config.CLIENT_ID, config.CLIENT_SECRET)
user = helix.user(config.USERNAME)

for mod in config.HANDLERS:
    module = import_module(f'..{mod}.bot', __name__)
    message_handlers.append(getattr(module, 'handle_message'))


class MessageHandler(Observer):

    "Message handling Observer"

    def on_completed(_):
        pass

    def on_error(_):