1extern crate rand;
2
3use rand::Rng;
4use std::ffi::{c_char, CStr, CString};
5use std::mem::transmute;
6
7use serde::{Deserialize as Deserialise, Serialize as Serialise};
8
9use twitcheventsub::*;
10
11pub struct TwitchEvents {
12 api: TwitchEventSubApi,
13}
14
15#[derive(Debug, Deserialise, Default)]
16pub struct UnitySubscriptions {
17 chat_message: bool,
18 user_update: bool,
19 follow: bool,
20 raid: bool,
21 update: bool,
22 new_subscription: bool,
23 subscription_end: bool,
24 gift_subscription: bool,
25 resubscription: bool,
26 cheer: bool,
27 points_custom_reward_redeem: bool,
28 points_auto_reward_redeem: bool,
29 poll_begin: bool,
30 poll_progress: bool,
31 poll_end: bool,
32 prediction_begin: bool,
33 prediction_progress: bool,
34 prediction_lock: bool,
35 prediction_end: bool,
36 goal_begin: bool,
37 goal_progress: bool,
38 goal_end: bool,
39 hype_train_begin: bool,
40 hype_train_progress: bool,
41 hype_train_end: bool,
42 shoutout_create: bool,
43 shoutout_receive: bool,
44 ban_timeout_user: bool,
45 delete_message: bool,
46 ad_break_begin: bool,
47}
48
49impl UnitySubscriptions {
50 pub fn new() -> UnitySubscriptions {
51 UnitySubscriptions {
52 user_update: false,
53 follow: true,
54 raid: true,
55 update: false,
56 new_subscription: true,
57 subscription_end: false,
58 gift_subscription: true,
59 resubscription: true,
60 cheer: true,
61 points_custom_reward_redeem: true,
62 points_auto_reward_redeem: true,
63 poll_begin: false,
64 poll_progress: false,
65 poll_end: false,
66 prediction_begin: false,
67 prediction_progress: false,
68 prediction_lock: false,
69 prediction_end: false,
70 goal_begin: false,
71 goal_progress: false,
72 goal_end: false,
73 hype_train_begin: false,
74 hype_train_progress: false,
75 hype_train_end: false,
76 shoutout_create: false,
77 shoutout_receive: false,
78 ban_timeout_user: false,
79 delete_message: false,
80 ad_break_begin: true,
81 chat_message: true,
82 }
83 }
84}
85
86#[no_mangle]
87pub extern "C" fn create_twitch_events(subscriptions: *const c_char) -> *mut TwitchEvents {
88 let keys = TwitchKeys::from_secrets_env().unwrap();
89 let subscriptions: UnitySubscriptions =
90 serde_json::from_str(unsafe { CStr::from_ptr(subscriptions) }.to_str().unwrap()).unwrap();
91
92 let mut twitch = TwitchEventSubApi::builder(keys.clone())
93 .set_redirect_url("http://localhost:3000")
94 .generate_new_token_if_insufficent_scope(true)
95 .generate_new_token_if_none(true)
96 .generate_access_token_on_expire(true)
97 .auto_save_load_created_tokens(".user_token.env", ".refresh_token.env");
98
99 if subscriptions.user_update {
100 twitch = twitch.add_subscription(Subscription::UserUpdate);
101 }
102 if subscriptions.follow {
103 twitch = twitch.add_subscription(Subscription::ChannelFollow);
104 }
105 if subscriptions.raid {
106 twitch = twitch.add_subscription(Subscription::ChannelRaid);
107 }
108 if subscriptions.update {
109 twitch = twitch.add_subscription(Subscription::ChannelUpdate);
110 }
111 if subscriptions.new_subscription {
112 twitch = twitch.add_subscription(Subscription::ChannelNewSubscription);
113 }
114 if subscriptions.subscription_end {
115 twitch = twitch.add_subscription(Subscription::ChannelSubscriptionEnd);
116 }
117 if subscriptions.gift_subscription {
118 twitch = twitch.add_subscription(Subscription::ChannelGiftSubscription);
119 }
120 if subscriptions.resubscription {
121 twitch = twitch.add_subscription(Subscription::ChannelResubscription);
122 }
123 if subscriptions.cheer {
124 twitch = twitch.add_subscription(Subscription::ChannelCheer);
125 }
126 if subscriptions.points_custom_reward_redeem {
127 twitch = twitch.add_subscription(Subscription::ChannelPointsCustomRewardRedeem);
128 }
129 if subscriptions.points_auto_reward_redeem {
130 twitch = twitch.add_subscription(Subscription::ChannelPointsAutoRewardRedeem);
131 }
132 if subscriptions.poll_begin {
133 twitch = twitch.add_subscription(Subscription::ChannelPollBegin);
134 }
135 if subscriptions.poll_progress {
136 twitch = twitch.add_subscription(Subscription::ChannelPollProgress);
137 }
138 if subscriptions.poll_end {
139 twitch = twitch.add_subscription(Subscription::ChannelPollEnd);
140 }
141 if subscriptions.prediction_begin {
142 twitch = twitch.add_subscription(Subscription::ChannelPredictionBegin);
143 }
144 if subscriptions.prediction_progress {
145 twitch = twitch.add_subscription(Subscription::ChannelPredictionProgress);
146 }
147 if subscriptions.prediction_lock {
148 twitch = twitch.add_subscription(Subscription::ChannelPredictionLock);
149 }
150 if subscriptions.prediction_end {
151 twitch = twitch.add_subscription(Subscription::ChannelPredictionEnd);
152 }
153 if subscriptions.goal_begin {
154 twitch = twitch.add_subscription(Subscription::ChannelGoalBegin);
155 }
156 if subscriptions.goal_progress {
157 twitch = twitch.add_subscription(Subscription::ChannelGoalProgress);
158 }
159 if subscriptions.goal_end {
160 twitch = twitch.add_subscription(Subscription::ChannelGoalEnd);
161 }
162 if subscriptions.hype_train_begin {
163 twitch = twitch.add_subscription(Subscription::ChannelHypeTrainBegin);
164 }
165 if subscriptions.hype_train_progress {
166 twitch = twitch.add_subscription(Subscription::ChannelHypeTrainProgress);
167 }
168 if subscriptions.hype_train_end {
169 twitch = twitch.add_subscription(Subscription::ChannelHypeTrainEnd);
170 }
171 if subscriptions.shoutout_create {
172 twitch = twitch.add_subscription(Subscription::ChannelShoutoutCreate);
173 }
174 if subscriptions.shoutout_receive {
175 twitch = twitch.add_subscription(Subscription::ChannelShoutoutReceive);
176 }
177 if subscriptions.ban_timeout_user {
178 twitch = twitch.add_subscription(Subscription::PermissionBanTimeoutUser);
179 }
180 if subscriptions.delete_message {
181 twitch = twitch.add_subscription(Subscription::PermissionDeleteMessage);
182 }
183 if subscriptions.ad_break_begin {
184 twitch = twitch.add_subscription(Subscription::AdBreakBegin);
185 }
186 if subscriptions.chat_message {
187 twitch = twitch.add_subscription(Subscription::ChatMessage);
188 }
189
190 let twitch = twitch.build().unwrap();
191
192 unsafe { transmute(Box::new(twitch)) }
193}
194
195#[repr(C)]
196pub struct EventData {
197 pub kind: CString,
198 pub json: CString,
199}
200
201impl EventData {
202 pub fn new() -> EventData {
203 EventData {
204 kind: CString::new("").unwrap(),
205 json: CString::new("").unwrap(),
206 }
207 }
208
209 pub fn kind(&self) -> CString {
210 self.kind.to_owned()
211 }
212
213 pub fn json(&self) -> CString {
214 self.json.to_owned()
215 }
216}
217
218#[no_mangle]
219pub extern "C" fn extract_type(event_data: *mut EventData) -> CString {
220 let event = unsafe { &mut *event_data };
221
222 event.kind()
223}
224
225#[no_mangle]
226pub extern "C" fn extract_json(event_data: *mut EventData) -> CString {
227 let event = unsafe { &mut *event_data };
228
229 event.json()
230}
231
232#[no_mangle]
233pub extern "C" fn get_event(twitch: *mut TwitchEvents) -> *mut EventData {
234 let twitch = unsafe { &mut *twitch };
235 let mut event = EventData::new();
236
237 for response in twitch.api.receive_all_messages(None) {
238 match response {
239 ResponseType::Event(event_a) => match event_a {
240 Event::ChatMessage(message_data) => {
241 println!("chat message recieved");
242 event.kind = CString::new(match message_data.message_type {
243 MessageType::PowerUpsGigantifiedEmote => "chat_message_powerup_gigantified_emote",
244 MessageType::PowerUpsMessageEffect => "chat_message_powerup_message_effect",
245 _ => "chat_message",
246 })
247 .unwrap();
248 event.json = CString::new(serde_json::to_string(&message_data).unwrap()).unwrap();
249 }
250 Event::PointsCustomRewardRedeem(custom_reward_redeem) => {
251 event.kind = CString::new("custom_point_reward_redeem").unwrap();
252 event.json = CString::new(serde_json::to_string(&custom_reward_redeem).unwrap()).unwrap();
253 }
254 Event::AdBreakBegin(ad_break_begin) => {
255 event.kind = CString::new("ad_break_start").unwrap();
256 event.json = CString::new(serde_json::to_string(&ad_break_begin).unwrap()).unwrap();
257 }
258 Event::Raid(raid) => {
259 event.kind = CString::new("raid").unwrap();
260 event.json = CString::new(serde_json::to_string(&raid).unwrap()).unwrap();
261 }
262 Event::Follow(follow) => {
263 event.kind = CString::new("follow").unwrap();
264 event.json = CString::new(serde_json::to_string(&follow).unwrap()).unwrap();
265 }
266 Event::NewSubscription(new_subscritpion) => {
267 event.kind = CString::new("new_subscription").unwrap();
268 event.json = CString::new(serde_json::to_string(&new_subscritpion).unwrap()).unwrap();
269 }
270 Event::GiftSubscription(gift) => {
271 event.kind = CString::new("subscription_gift").unwrap();
272 event.json = CString::new(serde_json::to_string(&gift).unwrap()).unwrap();
273 }
274 Event::Resubscription(resubscription) => {
275 event.kind = CString::new("resubscritpion").unwrap();
276 event.json = CString::new(serde_json::to_string(&resubscription).unwrap()).unwrap();
277 }
278 Event::Cheer(cheer) => {
279 event.kind = CString::new("cheer").unwrap();
280 event.json = CString::new(serde_json::to_string(&cheer).unwrap()).unwrap();
281 }
282 _ => {}
283 },
284
285 ResponseType::RawResponse(raw_string) => {
286 }
289 _ => {}
290 }
291 }
292
293 unsafe { transmute(Box::new(event)) }
294}
295
296#[no_mangle]
297pub extern "C" fn destroy_twitch_events(twitch_events: *mut TwitchEvents) {
298 let twitch: Box<TwitchEvents> = unsafe { transmute(twitch_events) };
299}