Jump to content

Writing a Twitch ChatGod program (Java/C#/Python?)

Hi all,

I'm a smaller twitch streamer and would like to write a program similar to DougDoug's ChatGod program, that reads chat messages in text-to-speech, allowing better interaction between myself and the chat. I have no idea where to start. I'm not very good at programming, and never have been. I've only written a very very simple GTA script in C#.

How would one go about writing such a program?

 

Link to post
Share on other sites

for a starter.. is there a *need* to write it yourself? there may already be software out there that does what you want it to do.

 

past that.. you can slice this up in 3 segments:

1: a hook into twitch chat. last time i've dabbled with this it was pretty much just IRC with some authentication on top. i assume it's more difficult now, but there should be plenty of guides out there.

2: ???

3: profit.  and a text to speech processor. from a quick google hit python has a library for this, i assume that windows has hooks for this for C# too.

 

the major problem is nr. 2. you need some sort of logic that protects you against things you may not want:

- people post profanities in chat, trolls posting "WWWWW", someone referring to "cape horn", and other stuff you want to filter out outright.

- do you cut out emoticons, "less than three", etc?

- handling chat going faster than TTS can voice it out. (does TTS go faster, does it skip messages, does it start lagging behind, how much  can it lag behind? etc.) might not be necessary immediately, but the edge case *will* happen.

Link to post
Share on other sites

46 minutes ago, manikyath said:

for a starter.. is there a *need* to write it yourself? there may already be software out there that does what you want it to do.

 

past that.. you can slice this up in 3 segments:

1: a hook into twitch chat. last time i've dabbled with this it was pretty much just IRC with some authentication on top. i assume it's more difficult now, but there should be plenty of guides out there.

2: ???

3: profit.  and a text to speech processor. from a quick google hit python has a library for this, i assume that windows has hooks for this for C# too.

 

the major problem is nr. 2. you need some sort of logic that protects you against things you may not want:

- people post profanities in chat, trolls posting "WWWWW", someone referring to "cape horn", and other stuff you want to filter out outright.

- do you cut out emoticons, "less than three", etc?

- handling chat going faster than TTS can voice it out. (does TTS go faster, does it skip messages, does it start lagging behind, how much  can it lag behind? etc.) might not be necessary immediately, but the edge case *will* happen.

I'm not sure if you've seen DougDoug's chat god streams/videos, but the idea is to have one specific user, either chosen manually or at random, to be able to talk to me.

Link to post
Share on other sites

This might start getting you on your way

 

 

https://github.com/MikeRaadsheer/TwitchBotCS

https://github.com/SimpleSandman/TwitchBot

 

I'm a learn by example type of person personally.

3735928559 - Beware of the dead beef

Link to post
Share on other sites

22 hours ago, wanderingfool2 said:

This might start getting you on your way

 

 

https://github.com/MikeRaadsheer/TwitchBotCS

https://github.com/SimpleSandman/TwitchBot

 

I'm a learn by example type of person personally.

Here's the code I have now.

Getting the following errors and not sure how to fix:

image.png.e852caf1e8b3cff6cdd9672ad261381c.png

image.png.805db0dea3cef824e857ed017dfb4618.png

If anyone knows a fix, lmk.

<>using Amazon;
using Amazon.Polly;
using Amazon.Polly.Model;
using TwitchLib.Api;
using TwitchLib.Api.Core.Exceptions;

namespace TwitchChatTextToSpeech
{
    class Program
    {
        private static TwitchAPI api;
        private static AmazonPollyClient pollyClient;
        private static List<string> lotteryEntries;
        private static Random random;

        static async Task Main(string[] args)
        {
            // Set up Twitch API client with oauth token
            api = new TwitchAPI();
            api.Settings.ClientId = "your_client_id";
            api.Settings.AccessToken = "your_oauth_token";

            // Validate oauth token
            try
            {
                var currentUser = await api.Helix.Users.GetUsersAsync();
            }
            catch (BadScopeException)
            {
                Console.WriteLine("The provided OAuth token does not have the necessary scopes to access Twitch API.");
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error validating OAuth token: {ex.Message}");
                return;
            }

            // Set up Amazon Polly client
            pollyClient = new AmazonPollyClient(RegionEndpoint.USWest2); // Change region as needed

            // Set up lottery and random number generator
            lotteryEntries = new List<string>();
            random = new Random();

            // Register Twitch chat event handler
            var chatService = new TwitchLib.Api.Services.TwitchChatService(api);
            chatService.ChatMessage += OnChatMessage;
            chatService.ListenAsync();

            Console.WriteLine("Twitch chat text-to-speech program started. Press any key to exit...");
            Console.ReadKey();
        }

        private static async void OnChatMessage(object sender, OnChatMessageArgs e)
        {
            string message = e.ChatMessage.Message;
            string username = e.ChatMessage.Username;

            // Add lottery entry
            if (message == "!enter")
            {
                if (!lotteryEntries.Contains(username))
                {
                    lotteryEntries.Add(username);
                    Console.WriteLine($"{username} entered the lottery.");
                }
            }

            // Roll lottery winner
            if (message == "!roll" && e.ChatMessage.IsModerator || e.ChatMessage.IsBroadcaster)
            {
                if (lotteryEntries.Count == 0)
                {
                    Console.WriteLine("No entries in the lottery.");
                }
                else
                {
                    int winnerIndex = random.Next(lotteryEntries.Count);
                    string winner = lotteryEntries[winnerIndex];
                    Console.WriteLine($"{winner} won the lottery!");
                    // Choose user manually
                    if (message.StartsWith("choose ") && (e.ChatMessage.IsModerator || e.ChatMessage.IsBroadcaster))
                    {
                        string chosenUser = message.Substring(7); // Get username from message
                        Console.WriteLine($"Manually chosen user: {chosenUser}");
                        // Convert text to speech using Amazon Polly
                        var request = new SynthesizeSpeechRequest
                        {
                            Text = $"{chosenUser} says: {File.ReadAllText($"{chosenUser}.txt")}",
                            VoiceId = VoiceId.Joanna,
                            OutputFormat = OutputFormat.Mp3
                        };
                        var response = await pollyClient.SynthesizeSpeechAsync(request);

                        // Play audio and delete file
                        using (Stream audioStream = response.AudioStream)
                        using (var audioPlayer = new System.Media.SoundPlayer(audioStream))
                        {
                            audioPlayer.PlaySync();
                        }
                        File.Delete($"{chosenUser}.mp3");

                        // Write chosen user to file
                        File.WriteAllText("chosen_user.txt", chosenUser);
                    }

                    // Save chat messages to file
                    File.WriteAllText($"{username}.txt", message);
                }
            }
        }
    }
}

Link to post
Share on other sites

I would look at 
https://github.com/MikeRaadsheer/TwitchBotCS/tree/master/MyShittyBot/MyShittyBot
And specifically the bot.cs file as an example.

 

I can't see TwitchChatService used at all in the example; so my guess is that it doesn't exist.

3735928559 - Beware of the dead beef

Link to post
Share on other sites

4 minutes ago, wanderingfool2 said:

I would look at 
https://github.com/MikeRaadsheer/TwitchBotCS/tree/master/MyShittyBot/MyShittyBot
And specifically the bot.cs file as an example.

 

I can't see TwitchChatService used at all in the example; so my guess is that it doesn't exist.

I'm very new to coding; what would be the right method to replace it?

Link to post
Share on other sites

for C# you have a class that already handle speaking a string value. Here's a basic class implementation with some QOL upgrades

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Speech.Synthesis;

public static class Voice
{
    private static SpeechSynthesizer synVoice = null;
    private static bool IsSpeaking = false;

    public static void Speak(string Text, bool WaitCompleted = false)
    {
        if (synVoice == null)
        {
            InitializeVoice();
        }
        synVoice.SpeakAsyncCancelAll();
        IsSpeaking = true;
        synVoice.SpeakAsync(Text);

        if (WaitCompleted)
        {
            while (IsSpeaking) { System.Windows.Forms.Application.DoEvents(); }
        }
    }

    private static void InitializeVoice()
    {
        synVoice = new SpeechSynthesizer();
        synVoice.SetOutputToDefaultAudioDevice();
        synVoice.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(Voice_SpeakCompleted);
    }

    private static void Voice_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
    {
        IsSpeaking = false;
    }
}

For reading twitch chat you have either the API route or parsing the content in the webpage.

Note that the audio output is hardcoded to use the default audio device but you can force one that you want specially if you are streaming because usually the default audio for you is not a channel that your viewer hear

Link to post
Share on other sites

On 4/21/2023 at 8:07 AM, Franck said:

for C# you have a class that already handle speaking a string value. Here's a basic class implementation with some QOL upgrades

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Speech.Synthesis;

public static class Voice
{
    private static SpeechSynthesizer synVoice = null;
    private static bool IsSpeaking = false;

    public static void Speak(string Text, bool WaitCompleted = false)
    {
        if (synVoice == null)
        {
            InitializeVoice();
        }
        synVoice.SpeakAsyncCancelAll();
        IsSpeaking = true;
        synVoice.SpeakAsync(Text);

        if (WaitCompleted)
        {
            while (IsSpeaking) { System.Windows.Forms.Application.DoEvents(); }
        }
    }

    private static void InitializeVoice()
    {
        synVoice = new SpeechSynthesizer();
        synVoice.SetOutputToDefaultAudioDevice();
        synVoice.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(Voice_SpeakCompleted);
    }

    private static void Voice_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
    {
        IsSpeaking = false;
    }
}

For reading twitch chat you have either the API route or parsing the content in the webpage.

Note that the audio output is hardcoded to use the default audio device but you can force one that you want specially if you are streaming because usually the default audio for you is not a channel that your viewer hear

I now have a complete and near functional, although very rudimentary, program. The code is below. However, I am getting an error where the command/terminal program closes immediately, with code 0. I cannot find a solution online other than adding Console.ReadLine() which I did. Any advice?

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Amazon;
using Amazon.Polly;
using Amazon.Polly.Model;
using TwitchLib.Client;
using TwitchLib.Client.Events;
using TwitchLib.Client.Models;
using TwitchLib.Api.Core;
// Set up Twitch chat client
var credentials = new ConnectionCredentials("BOT_USERNAME", "BOT_OUATH_TOKEN"); // your bot username, your ouath token
var client = new TwitchClient();
client.Initialize(credentials, "CHANNEL_USERNAME"); // your channel name
client.Connect();


// Set up Amazon Polly client
var awsCredentials = new Amazon.Runtime.BasicAWSCredentials("AWS_ID", "AWS_SECRET_ID"); // replace with your tokens
var pollyConfig = new AmazonPollyConfig
{
    RegionEndpoint = RegionEndpoint.USWest2, // Replace with your preferred AWS region
    UseHttp = true // Use HTTP instead of HTTPS
};
var pollyClient = new AmazonPollyClient(awsCredentials, pollyConfig);

// Set up list of usernames for TTS
var ttsUsernames = new List<string>() { "User1", "User2" }; // Replace with your desired usernames

// Set up output file paths
var speechDirectory = @"Path"; // Replace with your desired directory for speech files
var outputFilePath = Path.Combine(speechDirectory, "Message.txt"); //text file for messages

// Subscribe to Twitch chat events
client.OnMessageReceived += async (sender, e) =>
{
    if (ttsUsernames.Contains(e.ChatMessage.Username))
    {
        // Convert chat message to speech using Amazon Polly
        var pollyRequest = new SynthesizeSpeechRequest()
        {
            OutputFormat = OutputFormat.Mp3,
            Text = e.ChatMessage.Message,
            VoiceId = VoiceId.Joey // Replace with your desired Amazon Polly voice
        };
        var pollyResponse = await pollyClient.SynthesizeSpeechAsync(pollyRequest);

        // Write chat message to output file
        using (var outputFile = new StreamWriter(outputFilePath, true))
        {
            await outputFile.WriteLineAsync($"{e.ChatMessage.Message}");
        }

        // Save speech file to disk
        var speechFilePath = Path.Combine(speechDirectory, $"{e.ChatMessage.Message}.mp3");
        using (var outputStream = File.Create(speechFilePath))
        {
            await pollyResponse.AudioStream.CopyToAsync(outputStream);
        }
        var player = new System.Media.SoundPlayer(speechFilePath); // plays the file
        player.Play();
    }
    Console.ReadLine();

};

 

Link to post
Share on other sites

as far as i can see your code seems to be in the program.cs Also your Console.ReadLine() seems to be at the wrong position. It should be the last line of code. Reason is that the "OnMessageReceived is an event that will trigger many time over the time of the application so the Console.ReadLine() will let the program wait on that line of code until you press enter at which point it will stop and exit.

Link to post
Share on other sites

1 hour ago, Franck said:

as far as i can see your code seems to be in the program.cs Also your Console.ReadLine() seems to be at the wrong position. It should be the last line of code. Reason is that the "OnMessageReceived is an event that will trigger many time over the time of the application so the Console.ReadLine() will let the program wait on that line of code until you press enter at which point it will stop and exit.

In the time between my last message and this one, I managed to get the program working fully!

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×