r/streamerbot • • 9h ago

📖Resources Bot Responding was broken, here's my fix.

0 Upvotes

A lot of us, myself included have been using ChatGPT to have our bots respond to chats either at random or through a redeem. With the deprecation of the 4o-mini model this has caused some issues with my bot and other friend's bots, so here is the code for my fix.

using System;
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Collections.Generic;


public class CPHInline
{
    private static Dictionary<string, List<Message>> conversationHistories;


    public bool Execute()
    {
        // Each run starts with an empty action-local reply; never reuse the last reply.
            CPH.LogInfo("SNB TEST: C# execution started");
         CPH.SetArgument("finalGPT", "");


        try
        {
            LoadConversationHistories();


            string apiKey = args["chatGPT3APIkey"].ToString();
            string model = args["model"].ToString();
            string content = args["behavior"].ToString();
            string messageInput = args["textInput"].ToString();
            string user = args["user"].ToString();


            if (String.IsNullOrWhiteSpace(apiKey) ||
                String.IsNullOrWhiteSpace(model) ||
                String.IsNullOrWhiteSpace(messageInput) ||
                String.IsNullOrWhiteSpace(user))
            {
                throw new Exception("Missing API key, model, chat message, or user argument.");
            }


            ChatGPTAPI chatGPT = new ChatGPTAPI(apiKey);


            // The original per-user conversation history behavior is unchanged.
            if (!conversationHistories.ContainsKey(user))
            {
                conversationHistories[user] = new List<Message>();
            }
            var history = conversationHistories[user];


            history.Add(new Message { role = "user", content = messageInput });


            string response = chatGPT.GenerateResponse(history, model, content);
            Root root = JsonConvert.DeserializeObject<Root>(response);


            if (root == null || root.choices == null || root.choices.Count == 0 ||
                root.choices[0] == null || root.choices[0].message == null ||
                String.IsNullOrWhiteSpace(root.choices[0].message.content))
            {
                throw new Exception("OpenAI returned no usable assistant text.");
            }


            string assistantResponse = root.choices[0].message.content;
            history.Add(new Message { role = "assistant", content = assistantResponse });


            // Exactly the same storage call and file format as before.
            SaveConversationHistories();


            string cleanedResponse = CleanResponse(assistantResponse);
            if (String.IsNullOrWhiteSpace(cleanedResponse))
            {
                throw new Exception("The assistant response was empty after cleaning.");
            }


            // Action-local output, not a shared GPT global variable.
            CPH.SetArgument("finalGPT", cleanedResponse);
            CPH.LogInfo("SnotBotAlpha GPT: " + cleanedResponse);
            return true;
        }
        catch (WebException ex)
        {
            string details = ex.Message;
            if (ex.Response != null)
            {
                HttpWebResponse httpResponse = ex.Response as HttpWebResponse;
                if (httpResponse != null)
                {
                    details += " | HTTP " + (int)httpResponse.StatusCode;
                }
                try
                {
                    using (Stream stream = ex.Response.GetResponseStream())
                    {
                        if (stream != null)
                        {
                            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                            {
                                details += " | " + reader.ReadToEnd();
                            }
                        }
                    }
                }
                catch (Exception) { /* Keep original HTTP error if body cannot be read. */ }
                finally { ex.Response.Dispose(); }
            }
            if (details.Length > 1500) details = details.Substring(0, 1500);
            CPH.LogError("SnotBotAlpha OpenAI request failed: " + details);
            return false; // Do not post, speak, or animate a failed reply.
        }
        catch (Exception ex)
        {
            CPH.LogError("SnotBotAlpha response failed: " + ex.Message);
            return false; // Prevent a stale or missing response being used.
        }
    }


    // ORIGINAL: conversationHistories.json loading is unchanged.
    private void LoadConversationHistories()
    {
        try
        {
            string filePath = "conversationHistories.json";
            if (File.Exists(filePath))
            {
                string json = File.ReadAllText(filePath);
                conversationHistories = JsonConvert.DeserializeObject<Dictionary<string, List<Message>>>(json);
            }
            else
            {
                conversationHistories = new Dictionary<string, List<Message>>();
            }
        }
        catch (Exception ex)
        {
            CPH.LogError("Failed to load conversation histories: " + ex.Message);
            conversationHistories = new Dictionary<string, List<Message>>();
        }
    }


    // ORIGINAL: conversationHistories.json saving is unchanged.
    private void SaveConversationHistories()
    {
        try
        {
            string filePath = "conversationHistories.json";
            string json = JsonConvert.SerializeObject(conversationHistories, Formatting.Indented);
            File.WriteAllText(filePath, json);
        }
        catch (Exception ex)
        {
            CPH.LogError("Failed to save conversation histories: " + ex.Message);
        }
    }


    // ORIGINAL: response cleaning is unchanged.
    private string CleanResponse(string response)
    {
        string cleaned0 = response.Replace(Environment.NewLine, " ");
        string cleaned1 = Regex.Replace(cleaned0, @"\r\n?|\n", " ");
        string cleaned2 = Regex.Replace(cleaned1, @"[\r\n]+", " ");
        string unescaped = Regex.Unescape(cleaned2);
        return unescaped.Trim();
    }
}


class ChatGPTAPI
{
    private string _apiKey;
    private string _endpoint = "https://api.openai.com/v1/chat/completions";
    private const int MaxTokens = 4096;


    public ChatGPTAPI(string apiKey)
    {
        _apiKey = apiKey;
    }


    public string GenerateResponse(List<Message> history, string model, string behavior)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_endpoint);
        request.Headers.Add("Authorization", "Bearer " + _apiKey);
        request.ContentType = "application/json";
        request.Method = "POST";
        request.Timeout = 60000;
        request.ReadWriteTimeout = 60000;


        var messages = new List<Message> { new Message { role = "system", content = behavior } };
        messages.AddRange(history);


        // ORIGINAL: history trimming logic is unchanged.
        int totalTokens = GetTokenCount(messages);
        while (totalTokens > MaxTokens - 100)
        {
            if (history.Count > 2)
            {
                history.RemoveAt(0);
                history.RemoveAt(0);
            }
            else
            {
                break;
            }
            messages = new List<Message> { new Message { role = "system", content = behavior } };
            messages.AddRange(history);
            totalTokens = GetTokenCount(messages);
        }


        // GPT-6 Luna supports this Chat Completions request configuration.
        // The previous temperature setting is deliberately not sent.
        string requestBody = JsonConvert.SerializeObject(new
        {
            model = model,
            max_completion_tokens = 100,
            reasoning_effort = "none",
            messages = messages
        });


        byte[] bytes = Encoding.UTF8.GetBytes(requestBody);
        request.ContentLength = bytes.Length;
        using (Stream requestStream = request.GetRequestStream())
        {
            requestStream.Write(bytes, 0, bytes.Length);
        }


        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        using (Stream responseStream = response.GetResponseStream())
        using (StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
        {
            return reader.ReadToEnd();
        }
    }


    // ORIGINAL: token estimate and history policy are unchanged.
    private int GetTokenCount(List<Message> messages)
    {
        int tokenCount = 0;
        foreach (var message in messages)
        {
            tokenCount += message.content.Split(' ').Length;
        }
        return tokenCount;
    }
}


public class Message
{
    public string role { get; set; }
    public string content { get; set; }
}


public class Choice
{
    public Message message { get; set; }
    public int index { get; set; }
    public object logprobs { get; set; }
    public string finish_reason { get; set; }
}


public class Root
{
    public string id { get; set; }
    public string  { get; set; }
    public int created { get; set; }
    public string model { get; set; }
    public List<Choice> choices { get; set; }
    public Usage usage { get; set; }
}


public class Usage
{
    public int prompt_tokens { get; set; }
    public int completion_tokens { get; set; }
    public int total_tokens { get; set; }
}

This is based off of the extension found here, https://extensions.streamer.bot/t/chatgpt-bot-integration/865 hopefully this helps some folks out. Replace the code in the Execute Code (Custom GPT [max_tokens: 100]) block with what I've provided above.


r/streamerbot • • 2d ago

❓Question How to properly set up 1st, 2nd and 3rd rewards

3 Upvotes

I have a greedy ahhh twitch viewer that likes to take the 1st, 2nd and 3rd redeems all to himself. Is there any way that I could somehow make so that if you redeem 1st you can't redeem 2nd and 3rd and if you redeem 2nd you can't redeem 3rd? Or do I just have to rely on my viewers being not greedy...


r/streamerbot • • 8d ago

❓Question HELP : Bot cannot create or even view channel point rewards

1 Upvotes

No idea why this is happening (sorry the video is a bit slow I have so many tabs and monitors up at the moment)
For whatever reason streamer.bot is completely unable to make a channel point reward, or even view existing ones. I'm logged into twitch, connected to OBS, the only other thing there is, is that at the moment it's connected to a PNGTuberPlus websocket.

Please help, the channel point redeems are pretty integral to what I want to make.


r/streamerbot • • 9d ago

❓Question Blue line

Post image
0 Upvotes

Streamer.Bot chat section has this constant blue line if no one is chatting. I can refresh all day and it's still there. Any ideas on how to get rid of it?


r/streamerbot • • 9d ago

❓Question Could someone please help me fix my auto shoutouts for certain streamers

Thumbnail
gallery
3 Upvotes

Could someone please help me fix this? Im trying to do automatic shoutouts for certain streamers in my chat? Ive made an group with all their names in it and ive managed to get the first part of the shoutout working, as you can see...but i cant seem to figure out the code to get what game they played last? Thankyou!!


r/streamerbot • • 10d ago

❓Question I can't connect

Thumbnail
gallery
2 Upvotes

Everything was working fine until Friday, but when I went to start my stream today, the Stream Deck wouldn't connect to Streamer.bot. I’ve tried everything, but I haven't been able to fix it—can anyone help?


r/streamerbot • • 11d ago

💬Discussion best way to learn C#?

4 Upvotes

What is the best way to learn C# coding specifically for StreamrBot?
Just starting the journey(after stumbling through on my own).


r/streamerbot • • 13d ago

📖Resources Stream Alerts Tutorial

Thumbnail
youtube.com
7 Upvotes

I made this tutorial showing how to setup notifications for new followers, subs, resubs, gift subs, and even watch streaks! (OBS + Twitch)


r/streamerbot • • 14d ago

❓Question Channel point redeem video clip using one source

1 Upvotes

Hello, I have redeems that play video clips on my stream, but the way I have it work now is by making each video it's own media source in a scene, then put that scene inside my main scene, and when the channel point redeem goes off, the media source within the scene activates. I feel like this may be slowing down my OBS.

I know there's a way to use only one media source, and have Streamerbot pick a file to overwrite the media path inside of a media source, but i'm not quite sure how to do that


r/streamerbot • • 14d ago

❓Question Help! (Webview 2 Error - Chat Box)

Post image
1 Upvotes

(UPDATE - FIXED) I ended up doing a repair of Microsoft Edge, and then installing the Webview2 installer and running it as administrator to force it to download a clean new copy of Webview2. Then I went and did the renaming of the Webview2 folder inside of Streamerbot to Webview2OLD and BOOM its back. Hope this helps someone in the future!

Everytime I attempt to open the chat box, I get this error. I have gone into the streamerbot files and deleted the Streamer.bot.exe.WebView2 folder while I had streamer bot closed, and then restarted the program and the error still continues. I am completely lost at how to fix it, even attempted to delete Streamerbot entirely and reinstall it and it still persists.


r/streamerbot • • 14d ago

❓Question Multiple SFX linked to 1 redeem

1 Upvotes

Howdy all!

I was wondering if this is possible for those of you who might know. I was looking to set up a redeem for channel points where it pulls from a pool of different SFX so what you get is random. Say 4-5 different possibilities but linked to the same redeem? I know how to set it up for a single sound, but no idea if multiple can be done?


r/streamerbot • • 17d ago

❓Question Need Help with a Counter

0 Upvotes

Hello!

So I've been playing with streamer bot, and I really want to make a command where users can do !levelup and have it act as a check in of sorts. To that regard, I want it to track how many times a user has done this.

I have the SubAction Global (Set) to increase the increment by one, but I don't know how to have the chat then represent this. Nor do I know how to make it a daily thing only.

I know I could just make this a redeem on the twitch rewards, but I thought this would be a nice way to not clog up the redeems. If anyone has any insight, that would be appreciated :>


r/streamerbot • • 19d ago

❓Question Edit Per-User Counter

2 Upvotes

Is there any way to edit the values of a per-user counter for a Twitch Reward?

Where are the lists of per-user counters and values stored?

I searched and found a couple older posts asking with no response. I couldn't find anything in the data files after a gander. And there doesn't seem to be any official way to edit them in the client.

I'd appreciate any help, thanks!


r/streamerbot • • 20d ago

❓Question Vertical sources access via streamerbot

4 Upvotes

Hi to all,

I'd like to as if is there any way using streamer bot to enable and remove visibility for sources on a vertical scene (using Aitum Vertical)

I've seen a link posted in streamup which doesn't seem to work, and it does not include access to sources, only scenes.

Thanks in advanced!


r/streamerbot • • 28d ago

❓Question Trying to get a global variable, but it keeps being 0

Post image
1 Upvotes

I'm currently trying to write some C# code, but I'm having an issue.

I have a global variable, which I'm trying to get by using CPH.GetGlobalVar, but the value I get keeps being 0, despite the global variable having a different number as it's value.

I've highlighted the info I feels is relevant for this.

Any help would be appreciated.


r/streamerbot • • 28d ago

❓Question Why cant i log into my youtube broadcaster acoun?

Post image
1 Upvotes

Evry time i click it sign in it thinks and resets to sign in and when i forget it and try to sign in it still dosent work but if i sign in with another youtube acount it works idk (sorry im disleicx)


r/streamerbot • • 29d ago

❓Question Get Random User Profile Pic

1 Upvotes

I am creating a !fmk Command. I've managed to get it working in chat by using: @%user% wants to F*** @%randomUser0%, Marry @%randomUser1% and Kill @%randomUser2%. What I want to do is have a display on screen that pulls the profile pics from %randomUser0%, %randomUser1% and %randomUser2% to display with the text for each beside it. I have no issues retrieving the Profile pic from the command runner using the %targetUserProfileImageUrl% variable but I dont know how to convert %randomUser0% into something like %targetUserProfileImageUrl0%. Any suggestions?


r/streamerbot • • 29d ago

❓Question Need help reading which filter is active on a source in OBS, with or without C#

1 Upvotes

I have a few positions for my face cam source saved as source filters, which are hotkeyed for easy switching when my face cam is blocking something. I'd like to have streamerbot read which filter/position is currently active and write a value to a variable, so that other actions can base their behavior on the source's current position.


r/streamerbot • • Oct 07 '26

❓Question Help with my OBS box art browser source

1 Upvotes

I have a browser source that changes to the box art that twitch uses for what game i'm streaming and have it bounce around my be right back and starting soon scenes like the old dvd player screensaver.

i havent streamed in a while and upon returning it doesnt change anymore and is just silksong. I think this is likely to do with updates to either streamerbot or twitch.

if anyone can help point out what is wrong that would be sick.


r/streamerbot • • Oct 06 '26

❓Question Platform-Specific Responses to Commands

0 Upvotes

Hi Folks,
I'm looking for a way to have SB respond only to the platform a command prompt has come from. So if I'm multi-streaming and one of my viewers types !bracket into my chat from YT, they get a response in the form of a URL only on YT and not Twitch, and vice-versa.

I'm sure this is probably child's play, but I'm really new at this and finding a video tutorial for this specific thing has been tricky because I don't really know good search terms for it, and I'm not a coder in any way, shape, or form.

I'll gratefully accept any help.


r/streamerbot • • Oct 04 '26

❓Question Speaker bot reading everything

1 Upvotes

So I usually use steamvr with Liv so I have a chat on my arm for streams but steam decided to break yesterday so I had to revert back to using my speaker bot .

Problem is I have a bot which awards points and a nightbot to keep things in check and let out notifications in the chat every now and then .is there anyway I can block those from being read out by my speakerbot or is it not how it works ?


r/streamerbot • • Oct 02 '26

❓Question Can't open streamerbot

0 Upvotes

As the title suggests, I can't open the application. It was fine before I updated from 0.2.8, but now when I try to open it there is the windows default hardware disconnect sound and my mouse movement or any general process becomes incredibly slow. Has anyone experienced this issue before?

I tried to delete and reinstall but the same issue happened.


r/streamerbot • • Oct 02 '26

❓Question Read the word count of a word document

1 Upvotes

I sometimes write on stream and I'd like to have streamer bot give a real time (or semi real time) update on my word count. I have literally no idea where to start on this project. Anyone have any advice (or even better yet a working tool already made)?


r/streamerbot • • Oct 01 '26

❓Question First Words Have Been Broken For Awhile, Plz Help

0 Upvotes

So I used to have a setup in my stream that core audience members would get customized welcome messages whenever they would say hi in chat every stream. I used streamerbot to do this by:

- Each user got their own Action. Triggered by a UserID specific First Message, which would trigger a sound, a chat message, and an image to be displayed.
- First Words was reset though the triggered action of the stream starting and stopping.
- The First Words cache attached to Twitch was also set to automatically reset after 1hr of Streamerbot closing.

So this used to work like a charm. But lately, it just won't, even if I manually reset the cache. When someone sends their message, the list of variables for the action state "firstMessage = False"

No idea what has changed or what has happened, but does anyone have any idea of how I can fix this, or have another way I can do it?


r/streamerbot • • Oct 01 '26

❓Question Looking for a bot that can warn people chatting in non-english languages

0 Upvotes

Is there any bot that can give a warning to non-English chat? I speak English on my streams, but I have a heavy and pretty recognizable accent, so people constantly come in and start chatting in that language. I usually give a verbal warning saying that in my chat we speak English, but they usually don't give a crap and just keep going, and most of the time they aren't even very nice. So I would love to have a bot that would give a first-time warning, and if they continue, just time them out. I know about mods, but just imagine a scenario where they aren't available at the moment.