Интеграция с Twitch — получение ролей и имени в чате заглавными буквами

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

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

Хотя части ролей не имеют для меня такого высокого приоритета, я хочу, чтобы имена были правильно написаны с большой буквы.

Есть ли какой-нибудь трюк, который может это сделать?

using System;
using System.IO;
using System.Net.Sockets;
using UnityEngine;

public class TwitchConnect : MonoBehaviour
{
    public static TwitchConnect instance;

    public TwitchAccountData TwitchSettings = new();

    public event Action<string, string> OnChatMessage;
    public event Action<string> OnLoggedIn;
    public event Action OnLoggedOut;
    public event Action<string> OnInvalidLogin;

    public bool loggedIn = false;

    private TcpClient Twitch;
    private StreamReader Reader;
    private StreamWriter Writer;

    //private const string URL = "irc.chat.twitch.tv";
    private const string URL = "irc.twitch.tv";
    private const int PORT = 6667;

    private float PingCounter = 0;

    private string saveTwitchPath = "twitchauth.json";

    private void Awake()
    {
        DontDestroyOnLoad(gameObject);

        instance = this;

        saveTwitchPath = Application.persistentDataPath + "/twitchauth.json";

        LoadAccount();
    }

    public void UpdateAccount(string nUser, string nOAuth, string nChannel)
    {
        TwitchSettings.User = nUser;
        TwitchSettings.OAuth = nOAuth;
        TwitchSettings.Channel = nChannel;
    }

    public void ConnectToTwitch()
    {
        DisconnectFromTwitch();

        Twitch = new TcpClient(URL, PORT);
        Reader = new StreamReader(Twitch.GetStream());
        Writer = new StreamWriter(Twitch.GetStream());

        TwitchSettings.User = TwitchSettings.User.ToLower();
        TwitchSettings.Channel = TwitchSettings.Channel.ToLower();

        Writer.WriteLine("PASS " + TwitchSettings.OAuth);
        Writer.WriteLine("NICK " + TwitchSettings.User);
        Writer.WriteLine($"USER {TwitchSettings.User} 8 * :{TwitchSettings.User}");
        Writer.WriteLine("JOIN #" + TwitchSettings.Channel);
        Writer.Flush();//initiate connection
    }

    public void DisconnectFromTwitch()
    {
        loggedIn = false;
        PingCounter = 0;

        Twitch?.Dispose();
        Reader?.Dispose();
        Writer?.Dispose();

        Twitch = null;
        Reader = null;
        Writer = null;

        OnLoggedOut?.Invoke();
    }

    public void SaveAccount()
    {
        string jsonTwitch = JsonUtility.ToJson(TwitchSettings, true);
        File.WriteAllText(saveTwitchPath, jsonTwitch, System.Text.Encoding.Unicode);

        Debug.LogWarning("Twitch account settings saved!");
    }

    public void LoadAccount()
    {
        //twitch saved account settings - user, oauth, channel
        if (File.Exists(saveTwitchPath))
        {
            string jsonSettings = File.ReadAllText(saveTwitchPath, System.Text.Encoding.Unicode);
            JsonUtility.FromJsonOverwrite(jsonSettings, TwitchSettings);

            Debug.LogWarning("Twitch account loaded, logging in...");

            ConnectToTwitch();
        }
    }

    public void SendIrcMessage(string message)
    {
        Writer.WriteLine(message);
        Writer.Flush();
    }

    public void SendChatMessage(string message)
    {
        Writer.WriteLine($":{TwitchSettings.User}!{TwitchSettings.User}@{TwitchSettings.User}.tmi.twitch.tv PRIVMSG #{TwitchSettings.Channel} :{message}");
        Writer.Flush();
    }

    private void Update()
    {
        if (Twitch == null) return;

        if (!Twitch.Connected && loggedIn)
        {
            ConnectToTwitch();
        }

        PingCounter += Time.deltaTime;
        if (PingCounter > 50)
        {
            Writer.WriteLine("PING " + URL);
            Writer.Flush();
            PingCounter = 0;
        }
        
        if (Twitch.Available > 0)
        {
            string message = Reader.ReadLine();
#if UNITY_EDITOR
            Debug.Log(message);//DEBUG
#endif

            if (message.Contains("PRIVMSG"))
            {
                int splitPoint = message.IndexOf("!");
                string chatter = message[1..splitPoint];//get chatter name

                splitPoint = message.IndexOf(":", 1);
                string msg = message[(splitPoint + 1)..];//get message only

                OnChatMessage?.Invoke(chatter, msg);
            }
            else if (message.Contains(":Welcome, GLHF!"))//successful login
            {
                SaveAccount();

                loggedIn = true;
                OnLoggedIn?.Invoke(TwitchSettings.User);
            }
            else if (message.Contains(":Invalid NICK"))
            {
                OnInvalidLogin?.Invoke("Invalid NICK");
            }
            else if (message.Contains(":Improperly formatted auth"))
            {
                OnInvalidLogin?.Invoke("Improperly formatted auth");
            }
        }
    }

    private void OnDestroy()
    {
        DisconnectFromTwitch();
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
17
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы интерфейс TMI — Twitch Messaging Interface мог получить информацию об DisplayName и роли, вам необходимо включить некоторые возможности IRCv3, а затем обновить парсер для извлечения данных.

Перед PASS вы должны отправить

CAP REQ :twitch.tv/commands twitch.tv/tags

Так,

Writer.WriteLine("PASS " + TwitchSettings.OAuth);

становится

Writer.WriteLine("CAP REQ :twitch.tv/commands twitch.tv/tags");
Writer.WriteLine("PASS " + TwitchSettings.OAuth);

Чтобы включить дополнительные данные - https://dev.twitch.tv/docs/irc/возможности

Затем это добавит дополнительные данные к PRIVMSG, отправленным Twitch.

Их обычно называют тегами IRCv3.

Это пример из документации

@badge-info=;badges=broadcaster/1;client-nonce=28e05b1c83f1e916ca1710c44b014515;color=#0000FF;display-name=foofoo;emotes=62835:0-10;first-msg=0;flags=;id=f80a19d6-e35a-4273-82d0-cd87f614e767;mod=0;room-id=713936733;subscriber=0;tmi-sent-ts=1642696567751;turbo=0;user-id=713936733;user-type= :[email protected] PRIVMSG #bar :bleedPurple

https://dev.twitch.tv/docs/irc/отправить-получить-сообщения#прием-чат-сообщений

Этот пользователь:

  • отправил сообщение bleedpurple в канал bar
  • имеет display-name из foofoo это будет Capitislation пользователя, если он установлен пользователем
  • имеет значки broadcaster (версия 1 указанного значка)

Таким образом, для VIP или модератора вы должны следить за значками vip или moderator и так далее для любых ролей, которые вы ищете.

Дальнейшее чтение находится на https://dev.twitch.tv/docs/irc/tags#privmsg-теги

Некоторые примеры значков:

Comma-separated list of chat badges in the form, <badge>/<version>. For example, admin/1. There are many possible badge values, but here are few:
admin
bits
broadcaster
moderator
subscriber
staff
turbo

Обычно вы запрашиваете API значков (канальный или глобальный) для доступных значков и версий этих значков.

Но важные значки, основанные на ролях, находятся в этом неполном списке.

О, интересно, а если я включу CAP REQ, он всегда будет доступен или у него будут определенные каналы, которые его не поддерживают/не имеют?

Nevaran 13.05.2022 22:00

CAP REQ запрашивает у сервера активацию $thing, поэтому в все каналы вы ПРИСОЕДИНЯЕТЕСЬ.

Barry Carlyon 13.05.2022 23:21

Попался; после нескольких попыток переформатировать разбиение строки я понял это, и, похоже, это работает очень хорошо!

Nevaran 14.05.2022 02:54

Другие вопросы по теме