Skip to content

Instantly share code, notes, and snippets.

@xRahul
Created June 26, 2016 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xRahul/85f541ca860234b1db6e32f249fdfd79 to your computer and use it in GitHub Desktop.
Save xRahul/85f541ca860234b1db6e32f249fdfd79 to your computer and use it in GitHub Desktop.
Twitch.tv
<html>
<head>
<title>
Twitch.tv Streams
</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
// required variables and functions
const render = ReactDOM.render
const Redux = window.Redux
const Provider = ReactRedux.Provider
const createStore = Redux.createStore
const applyMiddleware = Redux.applyMiddleware
const combineReducers = Redux.combineReducers
const bindActionCreators = Redux.bindActionCreators
const compose = Redux.compose
const ReduxThunk = window.ReduxThunk.default
const Component = React.Component
const PropTypes = React.PropTypes
const connect = ReactRedux.connect
const classnames = window.classNames
const S = window.S
const CHANNEL_REQUEST = 'CHANNEL_REQUEST'
const CHANNEL_FAILED = 'CHANNEL_FAILED'
const CHANNEL_SUCCESS = 'CHANNEL_SUCCESS'
// reducer
function channels (state = {
channelNames: ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas", "brunofin", "comster404"],
channels: [],
currentChannel: '',
fetching: false,
failure: false
}, action) {
switch (action.type) {
case CHANNEL_REQUEST:
return Object.assign({}, state, {
fetching: true,
failure: false,
currentChannel: action.channel
})
case CHANNEL_FAILED:
return Object.assign({}, state, {
fetching: false,
failure: true,
currentChannel: action.channel
})
case CHANNEL_SUCCESS:
return Object.assign({}, state, {
fetching: false,
failure: false,
currentChannel: action.channel,
channels: [
...state.channels,
action.data
]
})
default:
return state
}
}
// actions
function requestChannel(channel) {
return {
type: CHANNEL_REQUEST,
channel: channel
}
}
function receiveChannel(channel,data) {
return {
type: CHANNEL_SUCCESS,
channel: channel,
data: data
}
}
function errorChannel(channel) {
return {
type: CHANNEL_FAILED,
channel: channel
}
}
// async action to fetch quote
function fetchChannels() {
return (dispatch,getState) => {
const state = getState()
const baseUrl = 'https://api.twitch.tv/kraken/'
const channelNames = state.channels.channelNames
channelNames.forEach(
(channel) => {
const streamUrl = baseUrl + "streams/" + channel + "?callback=?"
const channelUrl = baseUrl + "channels/" + channel + "?callback=?"
dispatch(requestChannel(channel))
$.getJSON(channelUrl)
.fail( () => dispatch(errorChannel(channel)) )
.done( (cdata) => {
$.getJSON(streamUrl)
.fail( () => dispatch(errorChannel(channel)) )
.done( (sdata) => {
const channelData = Object.assign({}, sdata, cdata, {
'channelName': channel
})
dispatch(receiveChannel(channel, channelData))
})
})
})
}
}
class ListItem extends Component {
render() {
const {channel} = this.props
const liClass = classNames({
'row': true,
'list-group-item': true,
'list-group-item-success': channel.stream !== null && channel.stream !== undefined,
'list-group-item-info': channel.stream === null,
'list-group-item-danger': channel.stream === undefined
})
const image = <img className="col-lg-1 col-md-1 col-sm-2 col-xs-2 img-responsive" src={channel.logo !== null && channel.logo !== undefined?channel.logo:"https://media.glassdoor.com/sqll/422050/square-squarelogo.png"} />
const channelNameView = <div className="paddingTop lead col-lg-3 col-md-3 col-sm-5 col-xs-5"><a href={channel.url !== undefined?channel.url:"#"}>{channel.display_name === undefined?channel.channelName:channel.display_name}</a></div>
let status = ''
let statusExtended = ''
if(channel.stream === undefined) {
status = "Channel Invalid"
}
else if(channel.stream === null) {
status = "Offline"
}
else {
status = channel.stream.game
statusExtended = " | " + channel.status
}
const statusView = <div className="paddingTop col-lg-8 col-md-8 col-sm-5 col-xs-5">{status}<span className="visible-lg-inline visible-md-inline">{statusExtended}</span></div>
return (
<li className={liClass}>
{image}
{' '}
{channelNameView}
{statusView}
</li>
)
}
}
class List extends Component {
componentDidMount() {
this.props.allProps.fetchChannels()
}
render() {
const { channelNames, channels, currentChannel,
fetching, failure } = this.props.allProps
const listItems = channels.map(
(channel, index) => <ListItem key={index} channel={channel} />
)
return (
<ul className="list-group">
{listItems}
</ul>
)
}
}
class App extends Component {
render() {
return (
<div className="container">
<div className="jumbotron">
<h1>Twitch.tv JSON api Streams/Channels</h1>
<p className="text-right">
{"By- "}
<a href="https://www.freecodecamp.com/xrahul">
Rahul Jain
</a>
</p>
</div>
<div className="jumbotron">
<List
allProps = {this.props}
/>
</div>
</div>
)
}
}
// helper functions for app container
function mapStateToProps(state) {
const { channels } = state
return {
...channels
}
}
function mapDispatchToProps(dispatch) {
return {
fetchChannels: () => dispatch(fetchChannels())
}
}
// create app container using connect()
const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App)
// create store using middlewares
const rootReducer = combineReducers({
channels
})
let store = createStore(
rootReducer,
compose(
applyMiddleware(ReduxThunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
)
// render the app to the page
render(
<Provider store={store}>
<AppContainer />
</Provider>
,document.getElementById('app'));
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://fb.me/react-15.1.0.js"></script>
<script src="https://fb.me/react-dom-15.1.0.js"></script>
<script src="https://npmcdn.com/redux@3.5.2/dist/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<script src="https://npmcdn.com/redux-thunk@2.0.1/dist/redux-thunk.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.5/index.min.js"></script>
<script src="https://cdn.bootcss.com/string.js/3.3.1/string.min.js"></script>
body {
margin-top: 5em;
font-family: 'Josefin Sans', sans-serif;
}
.paddingTop {
padding-top: 0.5em;
padding-bottom: 0.5em;
margin-bottom: 0;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment