diff --git a/UI/Controls/game_entry.gd b/UI/Controls/game_entry.gd index 4cb852c2..d50d6262 100644 --- a/UI/Controls/game_entry.gd +++ b/UI/Controls/game_entry.gd @@ -1,12 +1,15 @@ extends PanelContainer class_name GameEntry +const PROMOTE_ALERT_SCENE = preload("res://UI/Shoutouts/promote.tscn") enum Type {STEAM, ITCHIO} var type: Type var steam_app_id: int var itchio_app_url: String +var chatter: Chatter + var steam_data: SteamAppData var itchio_data: ItchIOAppData @@ -63,18 +66,21 @@ func _promote_game() -> void: var developer: String var description: String var link: String + var inst: Alert = PROMOTE_ALERT_SCENE.instantiate() + inst.chatter = chatter match type: Type.STEAM: title = steam_data.name developer = steam_data.developers.front() description = steam_data.short_description link = steam_data.s_team_url - pass + inst.steam = steam_data Type.ITCHIO: title = itchio_data.title developer = itchio_data.authors.front()["name"] description = itchio_data.description.left(200) + "..." link = itchio_data.url + inst.itch = itchio_data msg = msg.format({ "title": title, "developer": developer, @@ -82,6 +88,7 @@ func _promote_game() -> void: "link": link }) Globals.twitcher.send_message(msg) + EventManager.add_alert(inst) func _launch_game_site() -> void: var link: String diff --git a/UI/Controls/user_entry.gd b/UI/Controls/user_entry.gd index b384ee11..2ff94519 100644 --- a/UI/Controls/user_entry.gd +++ b/UI/Controls/user_entry.gd @@ -7,6 +7,7 @@ var tw_hidden: Tween var is_expanded: bool = false var is_profile_picture_loaded: bool = false +const SHOUTOUT_ALERT_SCENE := preload("res://UI/Shoutouts/shoutout.tscn") signal user_selected(chatter: Chatter) @@ -20,11 +21,18 @@ func _ready() -> void: %ScreenNotifer.rect = get_rect() %ScreenNotifer.screen_entered.connect(check_update_profile_picture) %User.pressed.connect(user_selected.emit.bind(chatter)) - %Shoutout.pressed.connect(func(): Globals.twitcher.shoutout(chatter.user)) + %Shoutout.pressed.connect(_handle_shoutout) #func(): Globals.twitcher.shoutout(chatter.user)) %Promote.pressed.connect(func(): Globals.twitcher.send_message(chatter.promo_msg)) %ButtonMenu.pressed.connect(func(): toggle_buttons(!is_expanded)) _update_tooltips() +func _handle_shoutout() -> void: + Globals.twitcher.shoutout(chatter.user) + Globals.twitcher.send_message(Globals.settings.shoutout_message.format(chatter.user)) + var alrt = SHOUTOUT_ALERT_SCENE.instantiate() + alrt.chatter = chatter + EventManager.add_alert(alrt) + func _update_tooltips() -> void: for node: Control in [%Shoutout, %Promote, %Refresh, %Raid, %Delete]: node.tooltip_text = node.tooltip_text % chatter.user.display_name diff --git a/UI/Panels/User/user_games.gd b/UI/Panels/User/user_games.gd index 6dfb25ca..e91e45b3 100644 --- a/UI/Panels/User/user_games.gd +++ b/UI/Panels/User/user_games.gd @@ -92,6 +92,7 @@ func populate_games() -> void: for game in chatter.steam_games: var inst: GameEntry = GAME_ENTRY.instantiate() inst.steam_app_id = game + inst.chatter = chatter inst.type = GameEntry.Type.STEAM inst.game_info_steam_pressed.connect(func(x: SteamAppData): %SteamAppPanel.show() @@ -102,6 +103,7 @@ func populate_games() -> void: for game in chatter.itch_games: var inst: GameEntry = GAME_ENTRY.instantiate() inst.itchio_app_url = chatter.itch_games[game] + inst.chatter = chatter inst.type = GameEntry.Type.ITCHIO inst.game_info_itchio_pressesd.connect(func(x: ItchIOAppData): %ItchAppPanel.show() diff --git a/UI/Shoutouts/promote.gd b/UI/Shoutouts/promote.gd new file mode 100644 index 00000000..4db2f3f2 --- /dev/null +++ b/UI/Shoutouts/promote.gd @@ -0,0 +1,51 @@ +extends Alert + +var chatter: Chatter +var itch: ItchIOAppData +var steam: SteamAppData + +var _updating_size: bool = false + +func _ready() -> void: + get_child(0).item_rect_changed.connect(func(): + if _updating_size: + return + _updating_size = true + size = get_child(0).size + get_child(0).position = Vector2.ZERO + _updating_size = false + ) + var rs := get_tree().root.size + position = Vector2(rs.x + 1000, ((rs.y / 2.0) - (size.y / 2.0))) + if not ((chatter and itch) or (chatter and steam)): + push_error("No chatter or game data set!") + await get_tree().create_timer(1.0).timeout + queue_free() + return + + %AvatarImg.texture = await ImageLoader.load_image(chatter.user.profile_image_url) + if %AvatarImg.texture == null: + %AvatarImg.texture = preload("res://assets/twitch_user_profile_pic.png") + + if itch: + _populate_itch() + else: + _populate_steam() + + await get_tree().process_frame + position = Vector2(rs.x + 20, ((rs.y / 2.0) - (size.y / 2.0))) + var tw := create_tween() + tw.tween_property(self, ^"position:x", rs.x - size.x - 20, 0.6) + tw.tween_interval(8) + tw.tween_property(self, ^"position:x", rs.x + 20, 0.6) + tw.tween_callback(self.queue_free) + +func _populate_itch() -> void: + %GameName.text = itch.title + %Description.text = itch.description + %GameBox.texture = await ImageLoader.load_image(itch.screenshots_thumbnails[0]) + +func _populate_steam() -> void: + %GameName.text = steam.name + %Description.text = steam.short_description + %GameBox.texture = await ImageLoader.load_image(steam.screenshots_thumbs[0]) \ No newline at end of file diff --git a/UI/Shoutouts/promote.gd.uid b/UI/Shoutouts/promote.gd.uid new file mode 100644 index 00000000..06ac8d38 --- /dev/null +++ b/UI/Shoutouts/promote.gd.uid @@ -0,0 +1 @@ +uid://dtgr8wqyjgegk diff --git a/UI/Shoutouts/promote.tscn b/UI/Shoutouts/promote.tscn new file mode 100644 index 00000000..786386ba --- /dev/null +++ b/UI/Shoutouts/promote.tscn @@ -0,0 +1,105 @@ +[gd_scene format=3 uid="uid://ce6yiwucniipu"] + +[ext_resource type="Texture2D" uid="uid://bu2juj2beyws7" path="res://assets/twitch_user_profile_pic.png" id="1_euwl6"] +[ext_resource type="Script" uid="uid://dtgr8wqyjgegk" path="res://UI/Shoutouts/promote.gd" id="1_m1b6q"] +[ext_resource type="FontFile" uid="uid://bh2gj03hg6v4r" path="res://assets/neon-wave-theme/polentical_neon/Polentical Neon Regular.ttf" id="3_4ipsx"] +[ext_resource type="Texture2D" uid="uid://cgglsphc6nng8" path="res://assets/sci_and_tech.png" id="4_pf7na"] + +[sub_resource type="LabelSettings" id="LabelSettings_e62tt"] +font_size = 36 + +[sub_resource type="LabelSettings" id="LabelSettings_y3o12"] +font = ExtResource("3_4ipsx") +font_size = 22 + +[node name="Promote" type="Control" unique_id=1922745758] +layout_mode = 3 +anchors_preset = 0 +offset_right = 400.0 +offset_bottom = 762.0 +script = ExtResource("1_m1b6q") + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=960598152] +clip_contents = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_type_variation = &"ShoutoutPanel" + +[node name="BG" type="VBoxContainer" parent="PanelContainer" unique_id=782434052] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="PanelContainer/BG" unique_id=1179407509] +clip_contents = true +custom_minimum_size = Vector2(0, 220) +layout_mode = 2 +theme_type_variation = &"ShoutoutInnerPanel" + +[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer/BG" unique_id=1907563848] +clip_children = 2 +clip_contents = true +custom_minimum_size = Vector2(0, 220) +layout_mode = 2 +size_flags_vertical = 3 +theme_type_variation = &"ShoutoutBottomPanel" + +[node name="GameBox" type="TextureRect" parent="PanelContainer/BG/PanelContainer2" unique_id=1272416027] +unique_name_in_owner = true +layout_mode = 2 +texture = ExtResource("4_pf7na") +expand_mode = 5 +stretch_mode = 6 + +[node name="ColorRect" type="ColorRect" parent="PanelContainer/BG/PanelContainer2" unique_id=1907105503] +layout_mode = 2 +color = Color(0.08235294, 0.08235294, 0.08235294, 0.627451) + +[node name="Content" type="VBoxContainer" parent="PanelContainer" unique_id=1609672363] +layout_mode = 2 + +[node name="Spacer" type="Control" parent="PanelContainer/Content" unique_id=1977205347] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="CenterContainer" type="CenterContainer" parent="PanelContainer/Content" unique_id=984731185] +layout_mode = 2 + +[node name="Portrait" type="PanelContainer" parent="PanelContainer/Content/CenterContainer" unique_id=927266204] +clip_children = 2 +clip_contents = true +layout_mode = 2 +theme_type_variation = &"PortraitBorder" + +[node name="AvatarImg" type="TextureRect" parent="PanelContainer/Content/CenterContainer/Portrait" unique_id=111606262] +unique_name_in_owner = true +custom_minimum_size = Vector2(250, 250) +layout_mode = 2 +texture = ExtResource("1_euwl6") +expand_mode = 1 +stretch_mode = 5 + +[node name="GameName" type="Label" parent="PanelContainer/Content" unique_id=1516712667] +unique_name_in_owner = true +layout_mode = 2 +text = "jevinscherriesgamedev" +label_settings = SubResource("LabelSettings_e62tt") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Spacer2" type="Control" parent="PanelContainer/Content" unique_id=1900817494] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="Description" type="Label" parent="PanelContainer/Content" unique_id=2061407605] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "$target is an amazing streamer. Go give them a follow!" +label_settings = SubResource("LabelSettings_y3o12") +horizontal_alignment = 1 +autowrap_mode = 2 +clip_text = true +text_overrun_behavior = 2 diff --git a/UI/Shoutouts/shoutout.gd b/UI/Shoutouts/shoutout.gd new file mode 100644 index 00000000..066c51d2 --- /dev/null +++ b/UI/Shoutouts/shoutout.gd @@ -0,0 +1,40 @@ +extends Alert + +var chatter: Chatter + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + var rs := get_tree().root.size + position = Vector2(rs.x + 20, ((rs.y / 2.0) - (size.y / 2.0))) + + if chatter == null: + return + + var game_id: String = "" + + if chatter.twitch_id in Globals.live_streamers.keys(): + game_id = Globals.live_streamers[chatter.twitch_id].game_id + else: + var resp := await Globals.twitcher.get_channel_information(chatter.twitch_id) + if resp: + var tci: TwitchChannelInformation = resp[chatter.twitch_id] + game_id = tci.game_id + + var gresp := await Globals.twitcher.get_games(game_id) + var gd: TwitchGame + if gresp: + gd = gresp[game_id] + + %AvatarImg.texture = await ImageLoader.load_image(chatter.user.profile_image_url) + if %AvatarImg.texture == null: + %AvatarImg.texture = preload("res://assets/twitch_user_profile_pic.png") + %DisplayName.text = chatter.user.display_name + %Message.text = Globals.settings.shoutout_alert_message.format({"target": chatter.user.display_name}) + %GameBox.texture = await ImageLoader.load_image(gd.box_art_url.format({"width": 600, "height": 800})) + %GameName.text = gd.name + + var tw := create_tween() + tw.tween_property(self, ^"position:x", rs.x - size.x - 20, 0.6) + tw.tween_interval(8) + tw.tween_property(self, ^"position:x", rs.x + 20, 0.6) + tw.tween_callback(self.queue_free) \ No newline at end of file diff --git a/UI/Shoutouts/shoutout.gd.uid b/UI/Shoutouts/shoutout.gd.uid new file mode 100644 index 00000000..1b0dba6d --- /dev/null +++ b/UI/Shoutouts/shoutout.gd.uid @@ -0,0 +1 @@ +uid://dssttgp6c8im7 diff --git a/UI/Shoutouts/shoutout.tscn b/UI/Shoutouts/shoutout.tscn new file mode 100644 index 00000000..f79cd68f --- /dev/null +++ b/UI/Shoutouts/shoutout.tscn @@ -0,0 +1,142 @@ +[gd_scene format=3 uid="uid://bhu2yvyvynwrp"] + +[ext_resource type="Texture2D" uid="uid://bu2juj2beyws7" path="res://assets/twitch_user_profile_pic.png" id="1_r3ok5"] +[ext_resource type="Script" uid="uid://dssttgp6c8im7" path="res://UI/Shoutouts/shoutout.gd" id="1_rllid"] +[ext_resource type="FontFile" uid="uid://c30qqiv6sqheh" path="res://assets/fonts/rage.woff2" id="2_r3ok5"] +[ext_resource type="FontFile" uid="uid://bh2gj03hg6v4r" path="res://assets/neon-wave-theme/polentical_neon/Polentical Neon Regular.ttf" id="3_up83n"] +[ext_resource type="FontFile" uid="uid://cx1a4aqqxhsrn" path="res://assets/neon-wave-theme/polentical_neon/Polentical Neon Italic.ttf" id="4_e62tt"] +[ext_resource type="Texture2D" uid="uid://cgglsphc6nng8" path="res://assets/sci_and_tech.png" id="4_y3o12"] + +[sub_resource type="LabelSettings" id="LabelSettings_e62tt"] +font = ExtResource("2_r3ok5") +font_size = 36 + +[sub_resource type="LabelSettings" id="LabelSettings_y3o12"] +font = ExtResource("3_up83n") +font_size = 22 + +[sub_resource type="LabelSettings" id="LabelSettings_rllid"] +font = ExtResource("4_e62tt") +font_size = 20 +font_color = Color(0, 1, 0.99215686, 1) +outline_size = 2 +shadow_size = 4 +shadow_color = Color(0, 0, 0, 0.9098039) +shadow_offset = Vector2(2, 2) + +[sub_resource type="LabelSettings" id="LabelSettings_uldix"] +font_size = 42 +outline_size = 2 +outline_color = Color(0, 0, 0, 1) + +[node name="Shoutout" type="Control" unique_id=1922745758] +layout_mode = 3 +anchors_preset = 0 +offset_right = 400.0 +offset_bottom = 762.0 +script = ExtResource("1_rllid") + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=960598152] +clip_contents = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_type_variation = &"ShoutoutPanel" + +[node name="BG" type="VBoxContainer" parent="PanelContainer" unique_id=782434052] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="PanelContainer/BG" unique_id=1179407509] +clip_contents = true +custom_minimum_size = Vector2(0, 220) +layout_mode = 2 +theme_type_variation = &"ShoutoutInnerPanel" + +[node name="Content" type="VBoxContainer" parent="PanelContainer" unique_id=1609672363] +layout_mode = 2 + +[node name="Spacer" type="Control" parent="PanelContainer/Content" unique_id=1977205347] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="CenterContainer" type="CenterContainer" parent="PanelContainer/Content" unique_id=984731185] +layout_mode = 2 + +[node name="Portrait" type="PanelContainer" parent="PanelContainer/Content/CenterContainer" unique_id=927266204] +clip_children = 2 +clip_contents = true +layout_mode = 2 +theme_type_variation = &"PortraitBorder" + +[node name="AvatarImg" type="TextureRect" parent="PanelContainer/Content/CenterContainer/Portrait" unique_id=111606262] +unique_name_in_owner = true +custom_minimum_size = Vector2(250, 250) +layout_mode = 2 +texture = ExtResource("1_r3ok5") +expand_mode = 1 +stretch_mode = 5 + +[node name="DisplayName" type="Label" parent="PanelContainer/Content" unique_id=1516712667] +unique_name_in_owner = true +layout_mode = 2 +text = "jevinscherriesgamedev" +label_settings = SubResource("LabelSettings_e62tt") +horizontal_alignment = 1 + +[node name="Spacer2" type="Control" parent="PanelContainer/Content" unique_id=1900817494] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="Message" type="Label" parent="PanelContainer/Content" unique_id=2061407605] +unique_name_in_owner = true +layout_mode = 2 +text = "$target is an amazing streamer. Go give them a follow!" +label_settings = SubResource("LabelSettings_y3o12") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Spacer3" type="Control" parent="PanelContainer/Content" unique_id=822690056] +custom_minimum_size = Vector2(0, 40) +layout_mode = 2 + +[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer/Content" unique_id=1907563848] +clip_children = 2 +clip_contents = true +custom_minimum_size = Vector2(0, 220) +layout_mode = 2 +theme_type_variation = &"ShoutoutBottomPanel" + +[node name="GameBox" type="TextureRect" parent="PanelContainer/Content/PanelContainer2" unique_id=1272416027] +unique_name_in_owner = true +layout_mode = 2 +texture = ExtResource("4_y3o12") +expand_mode = 3 +stretch_mode = 6 + +[node name="ColorRect" type="ColorRect" parent="PanelContainer/Content/PanelContainer2" unique_id=1907105503] +layout_mode = 2 +color = Color(0.08235294, 0.08235294, 0.08235294, 0.627451) + +[node name="CenterContainer" type="CenterContainer" parent="PanelContainer/Content/PanelContainer2" unique_id=598512574] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/Content/PanelContainer2/CenterContainer" unique_id=1410695648] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/Content/PanelContainer2/CenterContainer/VBoxContainer" unique_id=704682239] +layout_mode = 2 +text = "LAST SEEN STREAMING" +label_settings = SubResource("LabelSettings_rllid") +horizontal_alignment = 1 + +[node name="GameName" type="Label" parent="PanelContainer/Content/PanelContainer2/CenterContainer/VBoxContainer" unique_id=769516218] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +text = "Science & Technology" +label_settings = SubResource("LabelSettings_uldix") +horizontal_alignment = 1 +autowrap_mode = 2 diff --git a/assets/main_theme.tres b/assets/main_theme.tres index 85d249a9..0bba706d 100644 --- a/assets/main_theme.tres +++ b/assets/main_theme.tres @@ -33,6 +33,33 @@ corner_radius_top_right = 8 corner_radius_bottom_right = 8 corner_radius_bottom_left = 8 +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_d80jv"] +corner_radius_top_left = 300 +corner_radius_top_right = 300 +corner_radius_bottom_right = 300 +corner_radius_bottom_left = 300 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0arac"] +bg_color = Color(1, 1, 1, 1) +corner_radius_bottom_right = 42 +corner_radius_bottom_left = 42 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xgdp2"] +bg_color = Color(0.105868645, 0.3342936, 0.9625184, 1) +corner_radius_top_left = 42 +corner_radius_top_right = 42 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_64js0"] +bg_color = Color(0.18664144, 0.18664144, 0.18664144, 0.8627451) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +corner_radius_top_left = 45 +corner_radius_top_right = 45 +corner_radius_bottom_right = 45 +corner_radius_bottom_left = 45 + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ay4fc"] content_margin_left = 10.0 content_margin_top = 10.0 @@ -57,6 +84,14 @@ BlankButton/styles/pressed = SubResource("StyleBoxEmpty_u7u7u") Entry/base_type = &"PanelContainer" Entry/styles/panel = SubResource("StyleBoxFlat_frgrh") PanelContainer/styles/panel = SubResource("StyleBoxFlat_qhjvx") +PortraitBorder/base_type = &"PanelContainer" +PortraitBorder/styles/panel = SubResource("StyleBoxFlat_d80jv") +ShoutoutBottomPanel/base_type = &"PanelContainer" +ShoutoutBottomPanel/styles/panel = SubResource("StyleBoxFlat_0arac") +ShoutoutInnerPanel/base_type = &"PanelContainer" +ShoutoutInnerPanel/styles/panel = SubResource("StyleBoxFlat_xgdp2") +ShoutoutPanel/base_type = &"PanelContainer" +ShoutoutPanel/styles/panel = SubResource("StyleBoxFlat_64js0") TabPanel/base_type = &"PanelContainer" TabPanel/styles/panel = SubResource("StyleBoxFlat_ay4fc") TooltipLabel/styles/focus = SubResource("StyleBoxFlat_u7u7u") diff --git a/assets/sci_and_tech.png b/assets/sci_and_tech.png new file mode 100644 index 00000000..d1a07900 Binary files /dev/null and b/assets/sci_and_tech.png differ diff --git a/assets/sci_and_tech.png.import b/assets/sci_and_tech.png.import new file mode 100644 index 00000000..b0b668d8 --- /dev/null +++ b/assets/sci_and_tech.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cgglsphc6nng8" +path="res://.godot/imported/sci_and_tech.png-68424660a6c5759ee3a2dd43c4acecd3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sci_and_tech.png" +dest_files=["res://.godot/imported/sci_and_tech.png-68424660a6c5759ee3a2dd43c4acecd3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/lib/overlay_settings.gd b/lib/overlay_settings.gd index 6f092514..998b6e12 100644 --- a/lib/overlay_settings.gd +++ b/lib/overlay_settings.gd @@ -17,5 +17,8 @@ class_name OverlaySettings @export var display_screen: int = -1 +# Shoutout Message: +@export var shoutout_message: String = "@{target} is an amazing streamer. Go give them a follow!" +@export var shoutout_alert_message: String = "{target} is an amazing streamer. Go give them a follow!" @export var script_storage: Dictionary diff --git a/lib/twitcher_extended.zip b/lib/twitcher_extended.zip deleted file mode 100644 index 4e2f3b5f..00000000 Binary files a/lib/twitcher_extended.zip and /dev/null differ diff --git a/lib/twitcher_extended/twitcher_extended.gd b/lib/twitcher_extended/twitcher_extended.gd index 43c826eb..3ebbb260 100644 --- a/lib/twitcher_extended/twitcher_extended.gd +++ b/lib/twitcher_extended/twitcher_extended.gd @@ -10,6 +10,7 @@ signal chatbot_token_validated() #region Constants const POLL_TIMEOUT_MS: int = 30000 +const MAX_ITERS: int = 100 #endregion #region Static Exports @@ -68,6 +69,7 @@ var _cache_users: Dictionary[String, TwitchUser] = {} var _log: TwitchLogger = TwitchLogger.new("TwitcherExtended") var _commands: Dictionary[String, TwitchCommand] = {} var _is_processing_streams: bool = false +var _is_processing_games: bool = false #endregion enum AuthStatus { @@ -308,9 +310,15 @@ func reply_message(message: String, msg_id: String, as_streamer: bool = false) - func get_users_by_id(...user_ids: Array) -> Array[TwitchUser]: var tusers: Array[TwitchUser] = [] var qusers: Array[String] = [] - if user_ids[0] is Array: - user_ids = user_ids[0] - for user_id in user_ids: + var nusers: Array[String] = [] + + for x in user_ids: + if x is Array: + nusers.append_array(x) + else: + nusers.append(x) + + for user_id in nusers: if _cache_users.has(user_id): tusers.append(_cache_users[user_id]) else: @@ -332,11 +340,18 @@ func get_users_by_id(...user_ids: Array) -> Array[TwitchUser]: func get_users(...usernames: Array) -> Array[TwitchUser]: var tusers: Array[TwitchUser] = [] var qusers: Array[String] = [] + var nusers: Array[String] = [] - for i in usernames.size(): - usernames[i] = usernames[i].trim_prefix("@") + for x in usernames: + if x is Array: + nusers.append_array(x) + else: + nusers.append(x) - for username in usernames: + for i in nusers.size(): + nusers[i] = nusers[i].trim_prefix("@") + + for username in nusers: if _cache_users.has(username): tusers.append(_cache_users[username]) else: @@ -498,23 +513,30 @@ func get_cheermote(definition: TwitchCheermoteDefinition) -> Dictionary: #endregion #region Extended Methods -func get_live_streamers_data(user_ids: Array = []) -> Dictionary[String, TwitchStream]: +func get_live_streamers_data(...user_ids: Array) -> Dictionary[String, TwitchStream]: if _is_processing_streams: return {} _is_processing_streams = true if user_ids.is_empty(): var known := Globals.context.get_known_streamers() user_ids = known.map(func(x: Chatter): return x.twitch_id) + else: + var nusers: Array[String] = [] + for x in user_ids: + if x is Array: + nusers.append_array(x) + else: + nusers.append(x) + user_ids = nusers var streams_data: Dictionary[String, TwitchStream] = {} var opt := TwitchGetStreams.Opt.new() opt.type = "live" var iter: int = 0 - const MAX_ITER = 100 while not user_ids.is_empty(): iter += 1 - if iter > MAX_ITER: + if iter > MAX_ITERS: _log.e("Reached max iterations while getting live stream data.") break @@ -530,6 +552,47 @@ func get_live_streamers_data(user_ids: Array = []) -> Dictionary[String, TwitchS _is_processing_streams = false return streams_data +func get_streamer_data(...user_ids: Array) -> Dictionary[String, TwitchStream]: + var nusers: Array[String] = [] + if _is_processing_streams: + return {} + _is_processing_streams = true + + if user_ids.is_empty(): + var known = Globals.context.get_known_streamers() + user_ids = known.map(func(x: Chatter): return x.twitch_id) + else: + for x in user_ids: + if x is Array: + nusers.append_array(x) + else: + nusers.append(x) + user_ids = nusers + + var streams_data: Dictionary[String, TwitchStream] = {} + var opt := TwitchGetStreams.Opt.new() + opt.type = "all" + + var iter: int = 0 + while not user_ids.is_empty(): + iter += 1 + if iter > MAX_ITERS: + _log.e("Reached max iterations while getting stream data.") + break + + var new_batch: Array[String] = [] + new_batch.assign(user_ids.slice(0,99)) + user_ids = user_ids.slice(99) + opt.user_id = new_batch + var streams_iterator := await api.get_streams(opt) + for promise in streams_iterator: + var data: TwitchStream = await promise + if data: + streams_data[data.user_id] = data + + _is_processing_streams = false + return streams_data + func get_team_info(team_name: String) -> TwitchTeam: var opt := TwitchGetTeams.Opt.new() opt.name = team_name @@ -538,4 +601,69 @@ func get_team_info(team_name: String) -> TwitchTeam: return team_resp.data[0] else: return null + +func get_games(...game_ids: Array) -> Dictionary[String, TwitchGame]: + var ngames: Array[String] = [] + if game_ids.is_empty(): + push_error("Need to provide 1 or more game id's to get the game information.") + return {} + + if _is_processing_games: + return {} + + for x in game_ids: + if x is Array: + ngames.append_array(x) + else: + ngames.append(x) + game_ids = ngames + + var games_data: Dictionary[String, TwitchGame] = {} + var opt := TwitchGetGames.Opt.new() + + var iter: int = 0 + while not game_ids.is_empty(): + iter += 1 + if iter > MAX_ITERS: + _log.e("Reached max iterations while getting game information.") + break + + var new_batch: Array[String] = [] + new_batch.assign(game_ids.slice(0,99)) + game_ids = game_ids.slice(99) + opt.id = new_batch + var games := await api.get_games(opt) + for gi: TwitchGame in games.data: + games_data[gi.id] = gi + + _is_processing_games = false + return games_data + +func get_channel_information(...broadcaster_ids: Array) -> Dictionary[String, TwitchChannelInformation]: + var nchannels: Array[String] = [] + + for x in broadcaster_ids: + if x is Array: + nchannels.append_array(x) + else: + nchannels.append(x) + broadcaster_ids = nchannels + + var data: Dictionary[String, TwitchChannelInformation] = {} + var iter: int = 0 + while not broadcaster_ids.is_empty(): + iter += 1 + if iter > MAX_ITERS: + _log.e("Reached max iterations while getting game information.") + break + + var new_batch: Array[String] = [] + new_batch.assign(broadcaster_ids.slice(0,99)) + broadcaster_ids = broadcaster_ids.slice(99) + var resp := await api.get_channel_information(new_batch) + if resp != null: + for tci: TwitchChannelInformation in resp.data: + data[tci.broadcaster_id] = tci + + return data #endregion