Merge pull request #759 from lbryio/staging

Cut release from staging
This commit is contained in:
Shawn K 2018-11-27 10:24:28 -06:00 committed by GitHub
commit 481f81536f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 632 additions and 613 deletions

View file

@ -1,14 +1,14 @@
# Spee.ch
Spee.ch is a web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain. We encourage you to contribute to the shared code base, or fork it and make it your own.
Spee.ch is a [NodeJS](https://nodejs.org) React web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain.
You can create your own custom version of spee.ch by installing this code base and then creating your own custom components and styles to override the defaults. (More details/guide on how to do that coming soon.)
## Technology Overview
Spee.ch is a react web app that depends on MySQL for local content, and on two other lbry technologies:
Spee.ch depends on two other lbry technologies:
* [chainquery](https://github.com/lbryio/chainquery) - a normalized database of the blockchain data. We've provided credentials to use a public chainquery service. You can also install it on your own server to avoid being affected by the commons.
* [lbrynet](https://github.com/lbryio/lbry) - a daemon that handles your wallet and transactions.
![App GIF](https://spee.ch/e/speechgif.gif)
## Installation
## Install
### Ubuntu Step by Step
[Ubuntu Install Guide](./docs/ubuntuinstall.md)
@ -22,9 +22,14 @@ Spee.ch is a react web app that depends on MySQL for local content, and on two o
* speechport = 3000
#### Install and Set Up System Dependencies:
* Firewall open ports
* 22
* 80
* 443
* 3333
* 4444
* [NodeJS](https://nodejs.org)
* [MySQL](https://dev.mysql.com/doc/refman/8.0/en/installing.html)
* localhost port 3306
* mysqlusername or root
* mysqlpassword
* You may need
@ -38,12 +43,13 @@ Spee.ch is a react web app that depends on MySQL for local content, and on two o
* `./lbrynet account_balance` gets your balance (initially 0.0)
* `./lbrynet address_list` gets addresses you can use to recieve LBC
* [FFmpeg](https://www.ffmpeg.org/download.html)
* [Spee.ch] (below)
* [pm2] (optional) process manager such as pm2 to run speech server.js
* [http proxy server] caddy, nginx, traefik, etc to forward 80/443 to speech port 3000
* Spee.ch (below)
* pm2 (optional) process manager such as pm2 to run speech server.js
* http proxy server e.g. caddy, nginx, or traefik, to forward 80/443 to speech port 3000
* _note: even running on http://localhost, you must redirect http or https to port 3000_
#### Clone this repo
#### Clone a spee.ch repo (choose one)
* release version for stable production
```
$ git clone -b release https://github.com/lbryio/spee.ch.git
@ -65,7 +71,8 @@ $ npm install
```
#### Create the config files using the built-in CLI
_note: make sure lbrynet is running in the background before proceeding_
Make sure lbrynet is running in the background before proceeding.
_note: If you are opt to run a local chainquery, such as from [lbry-docker/chainquery](https://github.com/lbryio/lbry-docker/tree/master/chainquery) you will need to specify connection details at this time in:_ ~/spee.ch/docs/setup/conf/speech/chainqueryConfig.json
@ -75,7 +82,6 @@ $ npm run configure
#### Build & start the app
_note: make sure lbrynet is running in the background before proceeding_
```
$ npm run start
```
@ -249,3 +255,15 @@ Familiarity with the spee.ch code base and how the lbry daemon functions is requ
#### level 4
Issues with lbry (e.g. the spee.ch wallet, lbrynet configuration, etc.) that require strong familiarity with the lbry daemon and/or network to fix. Generally these issues are best suited for the `lbry` `protocol team` but are reported in this repo because they are part of the spee.ch implementation
## License
This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
## Security
We take security seriously. Please contact security@lbry.io regarding any security issues. [Our GPG key is here](https://lbry.io/faq/gpg-key) if you need it.
## Contact
The primary contact for this project is [@skhameneh](mailto:shawn@lbry.io).

View file

@ -1,16 +1,17 @@
.asset-preview-image {
.asset-preview__image {
width : 100%;
padding: 0;
margin : 0;
}
.asset-preview-video {
.asset-preview__video {
cursor: pointer;
background-color: #ffffff;
width: 100%;
position: relative;
}
h3.list-title {
h3.asset-preview__title {
margin: 0;
text-overflow: ellipsis;
word-wrap: break-word;
@ -18,3 +19,31 @@ h3.list-title {
line-height: 1em;
max-height: 2em;
}
.asset-preview__play-wrapper {
border: 0px;
padding: 0px;
margin: auto;
position: relative;
}
.asset-preview__play-overlay {
padding: 0;
border: 0;
position: absolute;
opacity: .50;
height: 50%;
top: 25%;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
margin: 0 auto;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Cg stroke='lightgray' stroke-width='2' fill='white' fill-rule='evenodd' stroke-linejoin='round'%3E %3Cpolygon points='5 21 5 3 21 12'/%3E %3C/g%3E %3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
}
.asset-preview__play-wrapper:hover .asset-preview__play-overlay {
opacity: 1.0;
}

View file

@ -15,11 +15,11 @@ const AssetPreview = ({ defaultThumbnail, claimData }) => {
<Link to={showUrl} className='asset-preview'>
<div>
<img
className={'asset-preview-image'}
className={'asset-preview__image'}
src={embedUrl}
alt={name}
/>
<h3 className='list-title'>{title}</h3>
<h3 className='asset-preview__title'>{title}</h3>
</div>
</Link>
);
@ -27,12 +27,15 @@ const AssetPreview = ({ defaultThumbnail, claimData }) => {
return (
<Link to={showUrl} className='asset-preview'>
<div>
<div className='asset-preview__play-wrapper'>
<img
className={'asset-preview-video'}
className={'asset-preview__video'}
src={thumbnail || defaultThumbnail}
alt={name}
/>
<h3 className='list-title'>{title}</h3>
<div className='asset-preview__play-overlay'></div>
</div>
<h3 className='asset-preview__title'>{title}</h3>
</div>
</Link>
);

View file

@ -18,20 +18,20 @@ class FaqPage extends React.Component {
</Row>
<Row>
<h3>OK But Why Should I Care?</h3>
<p>Spee.ch is a fast and easy way to host your images, videos, and other content. What makes this different from other similar sites is that Speech is hosted on the LBRY blockchain. That means it is impossible for your content to be censored via digital means. Even if we took down Speech today, all content would remain immutably stored on the LBRY blockchain.</p>
<p>Spee.ch is a fast and easy way to host your images, videos, and other content. What makes this different from other similar sites is that Spee.ch is hosted on the LBRY blockchain. That means it is impossible for your content to be censored via digital means. Even if we took down Spee.ch today, all content would remain immutably stored on the LBRY blockchain.</p>
<p>Blockchain technology doesnt solve <a href='https://xkcd.com/538/'>the 5 dollar wrench attack</a>, but it solves just about every other problem in media hosting and distribution.</p>
<p>Even better - you can host your own clone of Speech to get even more control over your content. <a href='https://github.com/lbryio/spee.ch/blob/master/README.md'>CLICK HERE FOR INFO</a>.</p>
<p>Speech is just the beginning of what will soon be a vibrant ecosystem of LBRY-powered apps. Use LBRY and youre one step closer to true freedom.</p>
<p>Even better - you can host your own clone of Spee.ch to get even more control over your content. <a href='https://github.com/lbryio/spee.ch/blob/master/README.md'>CLICK HERE FOR INFO</a>.</p>
<p>Spee.ch is just the beginning of what will soon be a vibrant ecosystem of LBRY-powered apps. Use LBRY and youre one step closer to true freedom.</p>
</Row>
<Row>
<h3>How to Use spee.ch</h3>
<p>Its easy. Drag the image or video file of your choice into the center of the spee.ch homepage.</p>
<p>Spee.ch is currently best suited for web optimized MP4 video and standard image filetypes (JPEG, GIF).</p>
<p>Spee.ch is currently best suited for web optimized MP4 video and standard image filetypes (JPEG, PNG, GIF).</p>
<p>If you want to refer to a piece of content repeatedly, or to build a collection of related content, you could create a channel. Channels work both for private collections and for public repositories. Theres more info about how to do this <a href='https://spee.ch/login'>on the channel page</a>.</p>
<p>Published files will be wiewable and embeddable with any web browser and accesible in the LBRY app. You can also use spee.ch to view free and non-NSFW content published on LBRY network from LBRY app. You just need to replace "lbry://" with "http://spee.ch/" in the URL.</p>
</Row>
<Row>
<h3>How Long Does Content Stay on Speech?</h3>
<h3>How Long Does Content Stay on Spee.ch?</h3>
<p>All content uploaded on spee.ch is guaranteed to stay up for at least 10 years with no maintenance. Future updates will likely extend that time horizon further as blockchain technology improves.</p>
</Row>
<Row>

View file

@ -12,15 +12,15 @@ class TosPage extends React.Component {
<Row>
<h1>Terms of Service</h1>
<p>Last updated: September 25, 2018</p>
<p>Please read these Terms of Service ("Terms", "Terms of Service") carefully before using the https://spee.ch website (the "Service") operated by LBRY INC ("us", "we", or "our").</p>
<p>Please read these Terms of Service ("Terms", "Terms of Service") carefully before using the <a className='link--primary' href='https://spee.ch'>https://spee.ch</a> website (the "Service") operated by <a className='link--primary' href='https://lbry.io'>LBRY INC</a> ("us", "we", or "our").</p>
<p>Your access to and use of the Service is conditioned upon your acceptance of and compliance with these Terms. These Terms apply to all visitors, users and others who wish to access or use the Service.</p>
<p>By accessing or using the Service you agree to be bound by these Terms. If you disagree with any part of the terms then you do not have permission to access the Service.</p>
</Row>
<Row>
<h3>Links To Other Web Sites</h3>
<p>Our Service may contain links to third party web sites or services that are not owned or controlled by LBRY INC</p>
<p>LBRY INC has no control over, and assumes no responsibility for the content, privacy policies, or practices of any third party web sites or services. We do not warrant the offerings of any of these entities/individuals or their websites.</p>
<p>You acknowledge and agree that LBRY INC shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use of or reliance on any such content, goods or services available on or through any such third party web sites or services.</p>
<p>Our Service may contain links to third party web sites or services that are not owned or controlled by <a className='link--primary' href='https://lbry.io'>LBRY INC</a></p>
<p><a className='link--primary' href='https://lbry.io'>LBRY INC</a> has no control over, and assumes no responsibility for the content, privacy policies, or practices of any third party web sites or services. We do not warrant the offerings of any of these entities/individuals or their websites.</p>
<p>You acknowledge and agree that <a className='link--primary' href='https://lbry.io'>LBRY INC</a> shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use of or reliance on any such content, goods or services available on or through any such third party web sites or services.</p>
<p>We strongly advise you to read the terms and conditions and privacy policies of any third party web sites or services that you visit.</p>
</Row>
<Row>
@ -34,12 +34,12 @@ class TosPage extends React.Component {
</Row>
<Row>
<h3>Limitation Of Liability</h3>
<p>In no event shall LBRY INC, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses, resulting from (i) your access to or use of or inability to access or use the Service; (ii) any conduct or content of any third party on the Service; (iii) any content obtained from the Service; and (iv) unauthorized access, use or alteration of your transmissions or content, whether based on warranty, contract, tort (including negligence) or any other legal theory, whether or not we have been informed of the possibility of such damage, and even if a remedy set forth herein is found to have failed of its essential purpose.</p>
<p>In no event shall <a className='link--primary' href='https://lbry.io'>LBRY INC</a>, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses, resulting from (i) your access to or use of or inability to access or use the Service; (ii) any conduct or content of any third party on the Service; (iii) any content obtained from the Service; and (iv) unauthorized access, use or alteration of your transmissions or content, whether based on warranty, contract, tort (including negligence) or any other legal theory, whether or not we have been informed of the possibility of such damage, and even if a remedy set forth herein is found to have failed of its essential purpose.</p>
</Row>
<Row>
<h3>Disclaimer</h3>
<p>Your use of the Service is at your sole risk. The Service is provided on an "AS IS" and "AS AVAILABLE" basis. The Service is provided without warranties of any kind, whether express or implied, including, but not limited to, implied warranties of merchantability, fitness for a particular purpose, non-infringement or course of performance.</p>
<p>LBRY INC its subsidiaries, affiliates, and its licensors do not warrant that a) the Service will function uninterrupted, secure or available at any particular time or location; b) any errors or defects will be corrected; c) the Service is free of viruses or other harmful components; or d) the results of using the Service will meet your requirements.</p>
<p><a className='link--primary' href='https://lbry.io'>LBRY INC</a> its subsidiaries, affiliates, and its licensors do not warrant that a) the Service will function uninterrupted, secure or available at any particular time or location; b) any errors or defects will be corrected; c) the Service is free of viruses or other harmful components; or d) the results of using the Service will meet your requirements.</p>
</Row>
<Row>
<h3>Exclusions</h3>

View file

@ -35,7 +35,7 @@ As root# _create user and add to sudo group_
usermod -aG sudo username
su - username
```
As username: _paste public key in authorized_keys_
As username: *paste public key in authorized\_keys*
```
`cd`
`mkdir .ssh`
@ -96,6 +96,7 @@ Log in as username@domainname or username@ip_address
`cp ~/spee.ch/docs/setup/conf/caddy/Caddyfile.template ~/spee.ch/docs/setup/conf/caddy/Caddyfile`
`nano ~/spee.ch/docs/setup/conf/caddy/Caddyfile`
( Change {{EXAMPLE.COM}} to YOURDOMAIN.COM )
`sudo cp ~/spee.ch/docs/setup/conf/caddy/Caddyfile /opt/caddy/`
@ -120,11 +121,17 @@ Log in as username@domainname or username@ip_address
At this point, navigating to yourdomain.com should give you a 502 bad gateway error. That's good!
Now you can make sure caddy starts when the machine starts:
`sudo systemctl enable caddy`
# 4 Set up MySQL
## Install MySQL
`sudo apt-get install mysql-server -y`
( enter blank password each time if prompted)
`sudo systemctl status mysql` (q to exit)
@ -132,7 +139,7 @@ Log in as username@domainname or username@ip_address
## Secure Setup
`sudo mysql_secure_installation`
* Password abcd1234
* Password your_mysql_password
* No to password validation
* Y to all other options
@ -143,7 +150,7 @@ Log in as username@domainname or username@ip_address
mysql>
`ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'abcd1234';`
`ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_mysql_password';`
mysql>
@ -153,13 +160,13 @@ Log in as username@domainname or username@ip_address
Verify:
`mysql -u root -p` and then entering your password abcd1234 should give you the mysql> shell
`mysql -u root -p` and then entering your_mysql_password should give you the mysql> shell
# 5 Get Lbrynet Daemon
## Start tmux
This just allows you to run multiple things in different sessions. Useful for manually starting daemons and watching its console logs.
tmux allows you to run multiple things in different sessions. Useful for manually starting daemons and watching its console logs.
`tmux`
* `Ctrl+b`, then `d` detaches leaving session running.
@ -175,11 +182,17 @@ This just allows you to run multiple things in different sessions. Useful for ma
`./lbrynet start`
## Detatch tmux session
* `Control + b`, then `d` to leave lbrynet daemon running and exit the session
`Control + b`, then `d`
<<<<<<< Updated upstream
* `tmux` if you want to get back into tmux
* `Control+b`, then `)` while in tmux session to cycle back to your lbrynet session to see output
=======
`tmux`
_note: `Control+b`, then `)` while in tmux session to cycle back to your lbrynet session to see output_
>>>>>>> Stashed changes
## Display wallet address to which to send 5+ LBC.
@ -214,9 +227,16 @@ This just allows you to run multiple things in different sessions. Useful for ma
`npm run configure`
<<<<<<< Updated upstream
=======
(once your wallet balance has cleared)
`npm run configure`
>>>>>>> Stashed changes
* Database: lbry
* Username: root
* Password: abcd1234
* Password: your_mysql_password
* Port: 3000
* Site Title: Your Site Name
* Enter your site's domain name: https://example.com or http://localhost

1015
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -94,9 +94,9 @@
"@babel/preset-react": "^7.0.0",
"@babel/preset-stage-2": "^7.0.0",
"@babel/register": "^7.0.0",
"babel-eslint": "9.0.0-beta.3",
"babel-loader": "^7.1.2",
"babel-plugin-module-resolver": "^3.1.1",
"babel-eslint": "9.0.0-beta.3",
"builder": "^4.0.0",
"chai": "^4.2.0",
"chai-http": "^4.2.0",

View file

@ -869,15 +869,35 @@ var claimQueries = (db, table, sequelize) => ({
});
},
getAllChannelClaims: async (channelClaimId, bidState) => {
getAllChannelClaims: async (channelClaimId, params) => {
logger$1.debug(`claim.getAllChannelClaims for ${channelClaimId}`);
const whereClause = bidState || {
[sequelize.Op.or]: [
{ bid_state: 'Controlling' },
{ bid_state: 'Active' },
{ bid_state: 'Accepted' },
],
const defaultWhereClauses = {
bid_state:
{ [sequelize.Op.or]: ['Controlling', 'Active', 'Accepted'] }
};
const addWhereClauses = (whereClauses, params) => {
/*
input params = { col: ['Val', 'Val']}
output = { col: { Op.or : [ { Op.eq: 'Value'},...]}, col2:...}
*/
const cols = Object.keys(params);
for (let colKey in cols){
let col = Object.keys(params)[colKey];
whereClauses[col] = {};
whereClauses[col][sequelize.Op.or] = [];
for (let itemKey in params[col] ){
let itemsArr = params[col];
whereClauses[col][sequelize.Op.or].push({ [sequelize.Op.eq]: itemsArr[itemKey] });
}
}
return whereClauses;
};
const whereClause = addWhereClauses(defaultWhereClauses, params);
const selectWhere = {
...whereClause,
publisher_id: channelClaimId,

View file

@ -68,15 +68,35 @@ export default (db, table, sequelize) => ({
});
},
getAllChannelClaims: async (channelClaimId, bidState) => {
getAllChannelClaims: async (channelClaimId, params) => {
logger.debug(`claim.getAllChannelClaims for ${channelClaimId}`);
const whereClause = bidState || {
[sequelize.Op.or]: [
{ bid_state: 'Controlling' },
{ bid_state: 'Active' },
{ bid_state: 'Accepted' },
],
const defaultWhereClauses = {
bid_state:
{ [sequelize.Op.or]: ['Controlling', 'Active', 'Accepted'] }
};
const addWhereClauses = (whereClauses, params) => {
/*
input params = { col: ['Val', 'Val']}
output = { col: { Op.or : [ { Op.eq: 'Value'},...]}, col2:...}
*/
const cols = Object.keys(params)
for (let colKey in cols){
let col = Object.keys(params)[colKey]
whereClauses[col] = {}
whereClauses[col][sequelize.Op.or] = []
for (let itemKey in params[col] ){
let itemsArr = params[col]
whereClauses[col][sequelize.Op.or].push({ [sequelize.Op.eq]: itemsArr[itemKey] })
}
}
return whereClauses;
}
const whereClause = addWhereClauses(defaultWhereClauses, params);
const selectWhere = {
...whereClause,
publisher_id: channelClaimId,

View file

@ -5,10 +5,16 @@ const { returnPaginatedChannelClaims } = require('./channelPagination.js');
const getChannelClaims = async (channelName, channelShortId, page) => {
const channelId = await chainquery.claim.queries.getLongClaimId(channelName, channelShortId);
const params = { content_type: [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'video/mp4',
] };
let channelClaims;
if (channelId) {
channelClaims = await chainquery.claim.queries.getAllChannelClaims(channelId);
channelClaims = await chainquery.claim.queries.getAllChannelClaims(channelId, params);
}
const processingChannelClaims = channelClaims ? channelClaims.map((claim) => getClaimData(claim)) : [];