add odysee

master
vampi 1 year ago
parent 288a9b1a27
commit 03d829c3f6

@ -0,0 +1,174 @@
if(typeof process === 'object') {
var fetch = require('node-fetch');
var EventEmitter = require('events');
}
class OdyseeApi extends EventEmitter {
constructor(settings) {
super();
settings = settings || {};
this.apiUrl = settings.apiUrl || 'https://api.odysee.com';
this.apiProxyUrl = settings.apiProxyUrl || 'https://api.na-backend.odysee.com/api/v1/proxy';
this.commentsApiUrl = settings.commentsApiUrl || 'https://comments.odysee.com/api/v2';
this.lbryAuthToken = settings.lbryAuthToken;
}
post(postData, options) {
return new Promise((resolve, reject) => {
var fetchData = {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(postData, 2)
};
this.emit('verbose', 'POST>' + fetchData.body);
if(!options || !options.noAuth) {
if(!this.authToken) {
reject(new Error('No access token'));
return;
}
fetchData.headers.authorization = this.authToken;
}
fetch(this.apiUrl, fetchData)
.then((response) => {
return response.json();
})
.then((json) => {
this.emit('verbose', 'POST<' + JSON.stringify(json));
if(json.error) {
reject(new Error(JSON.stringify(json.error)));
} else if(json.errors) {
reject(new Error(JSON.stringify(json.errors)));
} else {
if(json && json.data) {
resolve(json.data);
} else {
reject(new Error(json));
}
}
})
.catch((error) => {
reject(error);
})
;
});
}
loginWithAuthToken(email, authToken) {
return new Promise((resolve, reject) => {
if(!email) {
reject('User not specified');
return;
}
if(!authToken) {
reject('Auth token not specified');
return;
}
this.authToken = authToken;
resolve(true);
});
}
channelSign(channelId, lbryAuthToken, data) {
return fetch(this.apiProxyUrl + '?m=channel_sign', {
method: 'POST',
cache: 'no-cache',
headers: {
'Authority': 'api.na-backend.odysee.com',
'Content-type': 'application/json',
'x-lbry-auth-token': lbryAuthToken,
'content-type': 'application/json-rpc',
},
body: JSON.stringify({
jsonrpc: "2.0",
method: "channel_sign",
params: {
"channel_id":channelId,
"hexdata": Buffer.from(data).toString('hex')
}
})
}).then(response => response.json());
}
commentCreate(data) {
return fetch(this.commentsApiUrl+'?m=comment.Create', {
method: 'POST',
cache: 'no-cache',
headers: {
'Origin': 'https://odysee.com',
'Referer': 'https://odysee.com/',
'Content-type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'comment.Create',
params: data
})
}).then(response => response.json());
}
sendStreamChatMessage(message, channelName, channelId, claimId, lbryAuthToken) {
return new Promise((resolve, reject) => {
this.channelSign(channelId, lbryAuthToken, message).then(response => {
this.commentCreate({
comment: message,
channel_id: channelId,
channel_name: channelName,
claim_id: claimId,
signature: response.result.signature,
signing_ts: response.result.signing_ts
}).then(response => {
resolve(response);
});
});
});
}
apiPost(method, params) {
return new Promise((resolve, reject) => {
let body = new URLSearchParams(params).toString();
return fetch(this.apiUrl+'/'+method, {
headers: {
"content-type": "application/x-www-form-urlencoded",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site",
"sec-gpc": "1"
},
referrer: "https://odysee.com/",
referrerPolicy: "strict-origin-when-cross-origin",
body,
method: "POST",
mode: "cors",
credentials: "omit"
}).then(response => response.json()).then(response => {
if(response.success)
resolve(response.data)
else
reject(response.error);
});
});
}
userNew() {
return this.apiPost('user/new', {});
}
userSignin(auth_token, email, password) {
return this.apiPost('user/signin', { auth_token, email, password });
}
}
module.exports = OdyseeApi;

@ -0,0 +1,729 @@
if(typeof process === 'object') {
var Channel = require('./Channel');
}
class OdyseeChannel extends Channel {
constructor(chat, channelData) {
super(chat, channelData);
this.claim = channelData.claim;
this.messageSubId = this.chat.ws.startStreamMessageSubscription(this.claim);
this.viewerCount = 0;
this.state = 'joined';
setTimeout(() => {this.emit('joined');});
this.chat.ws.addListener('data', (data) => {
switch(data.type) {
case 'viewers':
if(data.data)
this.viewerCount = data.data.connected || 0;
break;
case 'delta':
// sticker
// {"type":"delta","data":{"comment":{"channel_id":"6a6f4ead96853304bec9647ade538f6009777c38","channel_name":"@vampirefrog","channel_url":"lbry://@vampirefrog#6a6f4ead96853304bec9647ade538f6009777c38","claim_id":"4d7499b149f4a3f40f58175d05dff7e925370556","comment":"\u003cstkr\u003e:SLIME:\u003cstkr\u003e","comment_id":"f9094fdf3cca3faa4bf931905551355456416bebe64616d21da012b843a9b45a","currency":"","is_fiat":false,"is_hidden":false,"is_pinned":false,"signature":"2570eb1b1ef709e2a68eb607ff3a1f489ec14f698d32f91744c0f295b0237a2581552ece96e53c696e49ed165aa1ce607020f2a18f5136ff583a6d921636dc1d","signing_ts":"1635634345","support_amount":0,"timestamp":1635634345}}}
// donation 1 lbc
// {"type":"delta","data":{"comment":{"channel_id":"6a6f4ead96853304bec9647ade538f6009777c38","channel_name":"@vampirefrog","channel_url":"lbry://@vampirefrog#6a6f4ead96853304bec9647ade538f6009777c38","claim_id":"4d7499b149f4a3f40f58175d05dff7e925370556","comment":"ding dong","comment_id":"2d17b811d779758a2252f8b3803a285907c52f7cf355ffb74157c05d8f710742","currency":"","is_fiat":false,"is_hidden":false,"is_pinned":false,"signature":"360c2490ae6d9fff41db1458f77a406634a181e349c23307c3b9c18666dc3ab28b32bfdd712a2eefd9017f03bb85aadca28c7b908d4e2c9e830544d5652a85c0","signing_ts":"1635634392","support_amount":1,"timestamp":1635634392}}}
if(data.data && data.data.comment) {
this.emit('message', {
type: 'chat',
id: data.data.comment.comment_id,
original: data.data,
username: data.data.comment.channel_name,
displayName: data.data.comment.channel_name,
avatar: null,
text: data.data.comment.comment,
spans: [data.data.comment.comment]
});
}
break;
}
});
}
sendChat(message) {
return new Promise((resolve, reject) => {
this.chat.api.sendStreamChatMessage(message, this.chat.channelName, this.chat.channelId, this.claim, this.chat.lbryAuthToken).then((message) => {
resolve(message);
}, (err) => {
reject(err);
});
});
}
_makeId(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
_getGiftValue(type) {
var giftValues = {
LEMON: 1,
ICE_CREAM: 10,
DIAMOND: 100,
NINJAGHINI: 1000,
NINJET: 10000
};
if(!type in giftValues)
return 1;
return giftValues[type];
}
_processEmotes(text, emotes) {
if(!emotes) {
return [ text ];
}
let spans = [];
let previ = 0;
for(let i = 0; i < emotes.length; i += 2) {
let emoteStart = emotes[i];
let emoteEnd = emotes[i + 1];
let between = text.substr(previ, emoteStart - previ);
let emote = text.substr(emoteStart, emoteEnd - emoteStart + 1);
spans.push(between);
spans.push({
type: 'image',
size: 'small',
class: 'emote',
src: 'https://images.prd.Odyseecdn.com/emoji/' + emote,
alt: emote
});
previ = emoteEnd + 1;
}
let last = text.substr(previ);
if(last) {
spans.push(last);
}
return spans;
}
handleStreamMessage(msg, source) {
var testMessages = {
Ban2: {"__typename":"ChatBan","type":"Ban","id":"chatban:Odysee-woabgpyuop|kaspaa","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-woabgpyuop","username":"Odysee-woabgpyuop","displayname":"M_o_h_a_m_a_d","avatar":"https://image.Odyseecdn.com/avatar/default7.png","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":false,"bannedBy":{"__typename":"StreamchatUser","id":"streamchatuser:kaspaa","username":"kaspaa","displayname":"Kaspaa","avatar":"https://images.prd.Odyseecdn.com/avatar/efd649c5-0378-11ea-9529-e2443572cd01","partnerStatus":"NONE"},"bannedByRoomRole":"Moderator"},
Ban: {"__typename":"ChatBan","type":"Ban","id":"chatban:Odysee-bzmuytbvmk|tctv","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-bzmuytbvmk","username":"Odysee-bzmuytbvmk","displayname":"PERKY_PAWG_BREAST","avatar":"https://image.Odyseecdn.com/avatar/default8.png","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":false,"bannedBy":{"__typename":"StreamchatUser","id":"streamchatuser:tctv","username":"tctv","displayname":"Tctv","avatar":"https://images.prd.Odyseecdn.com/avatar/9da26d8b-1ce5-11ea-9529-e2443572cd01","partnerStatus":"AFFILIATE"},"bannedByRoomRole":"Moderator"},
ExtendSub: {"__typename":"ChatExtendSub","id":"b9e5e15b-d754-46a4-b71d-63571975b09f","length":3,"month":1,"role":"None","roomRole":"Member","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/f85df577-6e2f-11ea-8119-a272e850df75","badges":[],"displayname":"PROPRBOY","effect":null,"id":"streamchatuser:proprboy","partnerStatus":"NONE","username":"proprboy"},"subscribing":true,"type":"ExtendSub"},
ExtendSub2: {"__typename":"ChatExtendSub","type":"ExtendSub","id":"0ac2a31f-eba4-42cd-980d-e4e524165c9d","sender":{"__typename":"StreamchatUser","id":"streamchatuser:datdoctor","username":"datdoctor","displayname":"WilliamDunham","avatar":"https://images.prd.Odyseecdn.com/avatar/f3559b21-3b9e-11ea-9fd3-a272e850df75","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"month":1,"length":1},
Follow: {"__typename":"ChatFollow","id":"f936fcb8-ebd5-4f88-9db6-6d4aa18e74d9","role":"None","roomRole":"Member","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/f7fda7f0-bc94-11ea-b737-e2443572cd01","badges":[],"displayname":"r-eVan","effect":null,"id":"streamchatuser:r-evan","partnerStatus":"NONE","username":"r-evan"},"subscribing":false,"type":"Follow"},
GiftSub: {"__typename":"ChatGiftSub","type":"GiftSub","id":"7c5741ce-4d68-4904-9a22-15c684bb936b","sender":{"__typename":"StreamchatUser","id":"streamchatuser:thomas42","username":"thomas42","displayname":"thomasthefam","avatar":"https://images.prd.Odyseecdn.com/avatar/69b8b18d-4432-11ea-9529-e2443572cd01","partnerStatus":"NONE","badges":[],"effect":"https://images.prd.Odyseecdn.com/effect/trxsmall"},"role":"None","roomRole":"Moderator","subscribing":true,"receiver":"greenbaywacky","count":null},
GiftSubReceive: {"__typename":"ChatGiftSubReceive","type":"GiftSubReceive","id":"6253dfab-10e0-47fd-889e-c8ada929ac02","sender":{"__typename":"StreamchatUser","id":"streamchatuser:greenbaywacky","username":"greenbaywacky","displayname":"greenbaywacky","avatar":"https://images.prd.Odyseecdn.com/avatar/f7672f4e-63f2-11e9-bc94-460601ac0a66","partnerStatus":"VERIFIED_PARTNER","badges":[],"effect":null},"role":"None","roomRole":"Moderator","subscribing":true,"gifter":"thomasthefam"},
Host: {"__typename":"ChatHost","id":"8ecb00e0-1061-4d52-804c-b5e7b5ef7ff4","role":"None","roomRole":"Member","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":false,"type":"Host","viewer":2},
Lemon: {"__typename":"ChatGift","type":"Gift","id":"688b3a22-34c0-4fe5-afbb-e82434013c35","sender":{"__typename":"StreamchatUser","id":"streamchatuser:soren.invicta","username":"soren.invicta","displayname":"Soren.Invicta","avatar":"https://image.Odyseecdn.com/avatar/default12.png","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"createdAt":"1610073419355881366","gift":"LEMON","amount":"1","recentCount":1,"expireDuration":0,"message":""},
Lemons: {"__typename":"ChatGift","amount":"5","createdAt":"1593804669046558744","expireDuration":0,"gift":"LEMON","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
IceCream: {"__typename":"ChatGift","amount":"1","createdAt":"1593804669046558744","expireDuration":0,"gift":"ICE_CREAM","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
IceCreams: {"__typename":"ChatGift","amount":"3","createdAt":"1593804669046558744","expireDuration":0,"gift":"ICE_CREAM","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
Diamond: {"__typename":"ChatGift","amount":"1","createdAt":"1593804669046558744","expireDuration":0,"gift":"DIAMOND","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","message":"Hello Frens","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
Diamond2: {"__typename":"ChatGift","type":"Gift","id":"a466fc18-58aa-4659-b166-012646cc144d","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-kphjutjxyt","username":"Odysee-kphjutjxyt","displayname":"97123_vegas","avatar":"https://images.prd.Odyseecdn.com/avatar/default20.png","partnerStatus":"NONE","badges":["CHRISTMAS_TREE","SANTA"],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"createdAt":"1609390512462873916","gift":"DIAMOND","amount":"1","recentCount":1,"expireDuration":0,"message":"2.00 a round for ammo now?"},
Diamond3: {"__typename":"ChatGift","type":"Gift","id":"a466fc18-58aa-4659-b166-012646cc144d","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-kphjutjxyt","username":"Odysee-kphjutjxyt","displayname":"97123_vegas","avatar":"https://images.prd.Odyseecdn.com/avatar/default20.png","partnerStatus":"NONE","badges":["CHRISTMAS_TREE","SANTA"],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"createdAt":"1609390512462873916","gift":"DIAMOND","amount":"1","recentCount":1,"expireDuration":0,"message":"pipipupu https://www.youtube.com/watch?v=3w-r3VtZl_k pupupuipi"},
Ninjaghini2: {"__typename":"ChatText","type":"Message","id":"fa701547-daa5-438d-a9b7-30c37dcf70d7","content":"6 ninjaghinis","createdAt":"1609390611166389797","subLength":1,"sender":{"__typename":"StreamchatUser","id":"streamchatuser:iamcheese","username":"iamcheese","displayname":"CEOofWamen","avatar":"https://images.prd.Odyseecdn.com/avatar/bd5c25ca-153b-11eb-aed2-be53b0f89a8c","partnerStatus":"NONE","badges":["CHRISTMAS_TREE"],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"emojis":[]},
Ninjaghini: {"__typename":"ChatGift","amount":"1","createdAt":"1593804669046558744","expireDuration":0,"gift":"NINJAGHINI","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","message":"Pee Pee poo Poo","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
Ninjet: {"__typename":"ChatGift","amount":"1","createdAt":"1593804669046558744","expireDuration":0,"gift":"NINJET","id":"5ac8bdb9-8e72-4418-8b37-d0e616e91098","message":"Dee Dee Get Out Of My laboratory","recentCount":1,"role":"None","roomRole":"Moderator","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/799c0ae0-a4e2-11ea-b737-e2443572cd01","badges":[],"displayname":"FerociousChihuahua","effect":null,"id":"streamchatuser:ferociouschihuahua","partnerStatus":"AFFILIATE","username":"ferociouschihuahua"},"subscribing":true,"type":"Gift"},
Mod: {"__typename":"ChatModerator","type":"Mod","id":"4ba35866-7b3d-4922-b1e0-a25907f9555e","sender":{"__typename":"StreamchatUser","id":"streamchatuser:thestoryofdori","username":"thestoryofdori","displayname":"TheStoryOfDori13","avatar":"https://images.prd.Odyseecdn.com/avatar/1b0c639f-208d-11ea-bd1e-563a837bad22","partnerStatus":"AFFILIATE","badges":[],"effect":"https://images.prd.Odyseecdn.com/effect/trx"},"role":"None","roomRole":"Moderator","subscribing":true,"add":true},
Subscription: {"__typename":"ChatSubscription","type":"Subscription","id":"cc51028f-4042-45b5-9b64-8ce03fb0b5c5","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-51995646","username":"Odysee-51995646","displayname":"GrimGriz","avatar":"https://images.prd.Odyseecdn.com/avatar/c8e244e6-5c97-11e9-ab17-865634f95b6b","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":true,"month":3},
SubStreak: {"__typename":"ChatSubStreak","id":"3bd0a19e-8791-410d-b3b2-9f044ba33881","length":2,"role":"None","roomRole":"Member","sender":{"__typename":"StreamchatUser","avatar":"https://images.prd.Odyseecdn.com/avatar/f85df577-6e2f-11ea-8119-a272e850df75","badges":[],"displayname":"PROPRBOY","effect":null,"id":"streamchatuser:proprboy","partnerStatus":"NONE","username":"proprboy"},"subscribing":true,"type":"SubStreak"},
TCValue: {"__typename":"ChatTCValueAdd","type":"TCValue","id":"47f8158d-2006-418f-9954-99c160349a5d","sender":{"__typename":"StreamchatUser","id":"streamchatuser:vampirefrog","username":"vampirefrog","displayname":"vampirefrog","avatar":"https://images.prd.Odyseecdn.com/avatar/e3d74c4e-d4fc-11ea-8cd4-c20daac9fa96","partnerStatus":"AFFILIATE","badges":[],"effect":null},"role":"None","roomRole":"Owner","subscribing":false,"amount":"3000000","totalAmount":"5139478"},
Timeout: {"__typename":"ChatTimeout","type":"Timeout","id":"0320ec61-2679-4a3e-9f61-c09bcddad6a0","sender":{"__typename":"StreamchatUser","id":"streamchatuser:Odysee-woabgpyuop","username":"Odysee-woabgpyuop","displayname":"M_o_h_a_m_a_d","avatar":"https://image.Odyseecdn.com/avatar/default7.png","partnerStatus":"NONE","badges":[],"effect":null},"role":"None","roomRole":"Member","subscribing":false,"bannedBy":{"__typename":"StreamchatUser","id":"streamchatuser:cascadiannationalist","username":"cascadiannationalist","displayname":"CascadiaPNW","avatar":"https://images.prd.Odyseecdn.com/avatar/52b10bde-b03d-11ea-b737-e2443572cd01","partnerStatus":"NONE"},"minute":5,"bannedByRoomRole":"Moderator"},
ValueUpdated: {"id":"1","payload":{"data":{"treasureChestMessageReceived":{"__typename":"TreasureChestValueUpdated","type":"ValueUpdated","value":"659998"}}},"type":"data"},
ValueUpdated2: {"payload":{"data":{"treasureChestMessageReceived":{"__typename":"TreasureChestValueUpdated","type":"ValueUpdated","value":"58949778"}}},"id":"1","type":"data"},
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": "not worth what they're asking right now",
// "createdAt": "1616108683715187197",
// "emojis": [],
// "id": "a2548765-a482-4915-8728-0afc02d32b9c",
// "role": "None",
// "roomRole": "Member",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/0645add3-77f0-11eb-8905-b23d0cea717c",
// "badges": [
// "CHRISTMAS_TREE"
// ],
// "displayname": "derwiking",
// "effect": null,
// "id": "streamchatuser:derwiking",
// "partnerStatus": "AFFILIATE",
// "username": "derwiking"
// },
// "subLength": 1,
// "subscribing": true,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": "sorry regs.....looks like I am gonna have to hire you....and meme too I guess",
// "createdAt": "1616108749441585339",
// "emojis": [],
// "id": "6a7128e8-a71e-4a10-9744-c06965826abe",
// "role": "None",
// "roomRole": "Member",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/010b90f7-70ca-11eb-8905-b23d0cea717c",
// "badges": [
// "CHRISTMAS_TREE",
// "SANTA"
// ],
// "displayname": "Rainbow_Raider",
// "effect": null,
// "id": "streamchatuser:Odysee-44756068",
// "partnerStatus": "NONE",
// "username": "Odysee-44756068"
// },
// "subLength": 16,
// "subscribing": true,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": "why is tts so slow, lol",
// "createdAt": "1616108964891998893",
// "emojis": [],
// "id": "27c35945-424f-4a06-84e0-5b6498d79073",
// "role": "None",
// "roomRole": "Member",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/cec35eae-59ed-11eb-8d87-b23d0cea717c",
// "badges": [],
// "displayname": "jon_jones",
// "effect": null,
// "id": "streamchatuser:soappy1",
// "partnerStatus": "NONE",
// "username": "soappy1"
// },
// "subLength": 1,
// "subscribing": true,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": "meme the t t s is being tarded",
// "createdAt": "1616108967093334840",
// "emojis": [],
// "id": "39966f91-fcfc-440b-b388-bbbd81c4517f",
// "role": "None",
// "roomRole": "Member",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/010b90f7-70ca-11eb-8905-b23d0cea717c",
// "badges": [
// "CHRISTMAS_TREE",
// "SANTA"
// ],
// "displayname": "Rainbow_Raider",
// "effect": null,
// "id": "streamchatuser:Odysee-44756068",
// "partnerStatus": "NONE",
// "username": "Odysee-44756068"
// },
// "subLength": 16,
// "subscribing": true,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": ":emote/mine/regulusmusic/36221b0860053aa_128128:",
// "createdAt": "1616109615426339442",
// "emojis": [],
// "id": "93533540-78f5-41ff-97a0-e3bf40a154de",
// "role": "None",
// "roomRole": "Moderator",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/a4b3b02b-60ba-11e9-bc94-460601ac0a66",
// "badges": [
// "FOUNDING_MEMBER"
// ],
// "displayname": "RegulusMusic",
// "effect": null,
// "id": "streamchatuser:regulusmusic",
// "partnerStatus": "AFFILIATE",
// "username": "regulusmusic"
// },
// "subLength": 14,
// "subscribing": true,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
// {
// "id": "2",
// "payload": {
// "data": {
// "streamMessageReceived": [
// {
// "__typename": "ChatText",
// "content": "hey mememan ",
// "createdAt": "1616111126563039849",
// "emojis": [],
// "id": "0551be02-84a8-4056-8e14-67a0c1c5d288",
// "role": "None",
// "roomRole": "Moderator",
// "sender": {
// "__typename": "StreamchatUser",
// "avatar": "https://images.prd.Odyseecdn.com/avatar/d4402057-15a5-11eb-b3bd-626a2067d975",
// "badges": [
// "CHRISTMAS_TREE"
// ],
// "displayname": "MarkusDP",
// "effect": null,
// "id": "streamchatuser:markusdp",
// "partnerStatus": "VERIFIED_PARTNER",
// "username": "markusdp"
// },
// "subLength": 0,
// "subscribing": false,
// "type": "Message"
// }
// ]
// }
// },
// "type": "data"
// }
};
if(msg.type == 'Message' && this.username == msg.sender.username && testMessages[msg.content]) {
msg = testMessages[msg.content];
msg.id = this._makeId(24);
}
switch(msg.type) {
case 'Message':
{
let spans = [];
var text = msg.content;
var m = text.match(/:emote\/([^/]+)\/([^/]+)\/([^:]+):/);
if(m && m[3]) {
// If we detect a sticker
spans.push({
type: 'image',
size: 'large',
class: 'sticker',
src: 'https://images.prd.Odyseecdn.com/emote/'+m[3],
alt: m[3]
});
this.emit('message', {
type: 'chat',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
text: text,
spans: spans
});
} else {
this.emit('message', {
type: 'chat',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
text: text,
spans: this._processEmotes(text, msg.emojis)
});
}
}
break;
case 'Gift':
this.emit('message', {
type: 'gift',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
message: msg.message,
giftType: msg.gift,
currency: 'LEMON',
value: this._getGiftValue(msg.gift),
amount: parseInt(msg.amount)
});
break;
case 'Follow':
this.emit('message', {
type: 'follow',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar
});
break;
case 'Host':
this.emit('message', {
type: 'host',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
viewers: msg.viewer
});
break;
case 'Subscription':
this.emit('message', {
type: 'subscribe',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
months: msg.month
});
break;
case 'ExtendSub':
this.emit('message', {
type: 'resubscribe',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
length: msg.length,
months: msg.month
});
break;
case 'GiftSub':
this.emit('message', {
type: 'giftSub',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
receiver: msg.receiver
});
break;
case 'GiftSubReceive':
this.emit('message', {
type: 'giftSubReceive',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
gifter: msg.gifter
});
break;
case 'SubStreak':
this.emit('message', {
type: 'subStreak',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
length: msg.length
});
break;
case 'TCValue':
this.emit('message', {
type: 'chestValue',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
currency: 'lemon',
currencyPlural: 'lemons',
amount: msg.amount / 100000.0,
totalAmount: msg.totalAmount / 100000.0
});
break;
case 'TCValueAdd':
break;
case 'Clip':
break;
case 'Delete':
this.emit('message', {
type: 'delete',
id: msg.id,
original: msg,
ids: msg.ids
});
break;
case 'Ban':
this.emit('message', {
type: 'ban',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
bannedByUsername: msg.bannedBy.username,
bannedByDisplayName: msg.bannedBy.displayname,
bannedByAvatar: msg.bannedBy.avatar,
bannedByPartnerStatus: msg.bannedBy.partnerStatus,
bannedByRoomRole: msg.bannedByRoomRole
});
break;
case 'Timeout':
// Timeout is from 1 to 60 minutes
this.emit('message', {
type: 'timeout',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
seconds: msg.minute * 60
});
break;
case 'Mod':
this.emit('message', {
type: 'moderator',
id: msg.id,
original: msg,
username: msg.sender.username,
displayName: msg.sender.displayname,
avatar: msg.sender.avatar,
add: msg.add
});
break;
case 'ChangeMode':
break;
case 'EmoteAdd':
break;
default:
this.emit('message', {
type: 'unknown',
id: msg.id,
original: msg
});
break;
}
}
isJoined() {
return this.state == 'joined';
}
getNumViewers() {
return new Promise((resolve, reject) => {
resolve({ viewers: this.viewerCount, platform: this.chat.getPlatformName() });
});
}
getStatus(original) {
return new Promise((resolve, reject) => {
this.chat.api.post({
operationName: 'LivestreamPageRefetch',
variables: {
username: this.username
},
query: `
query LivestreamPageRefetch(
$username: String!
) {
user(username: $username) {
avatar
chatDisabled
chatInterval
chatLinkDisabled
chatMode
chatVerifiedOnly
displayname
donateDisabled
effect
followChatDelay
isFollowing
isMe
isSubscribing
followers {
totalCount
}
following {
totalCount
}
ongoingGiftSub {
gifter {
displayname
id
username
avatar
}
count
}
partnerStatus
role
subscribeDisabled
username
livestream {
id
permlink
title
totalReward
watchingCount
createdAt
category {
id
title
}
creator {
displayname
id
username
}
language {
id
language
}
thumbnailUrl
ageRestriction
earnRestriction
}
subSetting {
badgeColor
badgeText
benefits
streakTextColor
textColor
}
}
}
`
}).then((data) => {
if(original) {
resolve(data);
return;
}
if(!data || !data.user) {
reject(data ? data : 'No data');
return;
}
resolve({
platform: this.chat.getPlatformName(),
clientId: this.chat.id,
channelId: this.id,
user: {
avatar: data.user.avatar,
displayName: data.user.displayname,
followers: data.user.followers.totalCount,
following: data.user.following.totalCount,
},
stream: data.user.livestream ? {
isLive: true,
startTime: data.user.livestream.createdAt / 1000,
viewers: data.user.livestream.watchingCount,
title: data.user.livestream.title,
preview: data.user.livestream.thumbnailUrl,
language: data.user.livestream.language.language,
audienceType: data.user.livestream.ageRestriction ? 'X-Tag' : data.user.livestream.earnRestriction ? 'Mature-Tag' : null,
category: {
id: data.user.livestream.category.id,
name: data.user.livestream.category.title,
}
} : { isLive: false },
chat: {
interval: data.user.chatInterval
}
});
}, reject);
});
}
}
if(typeof process === 'object') {
module.exports = OdyseeChannel;
}

@ -0,0 +1,95 @@
// node.js only
var Chat = require('./Chat');
var OdyseeChannel = require('./OdyseeChannel');
var OdyseeSocket = require('./OdyseeSocket');
var OdyseeApi = require('./OdyseeApi');
var fetch = require('node-fetch');
class OdyseeChat extends Chat {
constructor(settings) {
super(settings);
settings = settings || {};
this.ws = new OdyseeSocket({ claim: settings.claim });
this.ws.addListener('verbose', (msg) => { this.log(msg); });
this.api = new OdyseeApi(settings.apiUrl);
this.api.addListener('verbose', (msg) => { this.log(msg); });
this.channelName = settings.channelName;
this.channelId = settings.channelId;
if(settings.lbryAuthToken) {
this.lbryAuthToken = settings.lbryAuthToken;
setTimeout(() => {
this.state = 'ready';
this.emit('ready');
});
} else {
this.api.userNew().then(response => {
this.lbryAuthToken = response.auth_token
if(settings.username && settings.password) {
this.api.userSignin(this.lbryAuthToken, settings.username, settings.password).then(response => {
this.state = 'ready';
this.emit('ready');
}).catch(e => {
console.error('Error signing in to Odysee', e);
});
}
}).catch(e => {
console.error('Error getting Odysee auth token', e);
});
}
// if(settings.email) {
// if(settings.authToken) {
// this.log('logging in with access token', settings.email);
// this.api.loginWithAuthToken(settings.email, settings.authToken)
// .then((login) => {
// this.state = 'ready';
// this.emit('ready');
// }, (err) => {
// throw new Error('Could not login with authToken: '+err.toString());
// })
// ;
// } else if(settings.password) {
// this.api.login(settings.email, settings.password)
// .then((login) => {
// this.state = 'ready';
// this.emit('ready');
// }, (err) => {
// throw new Error('Could not login with password: '+err.toString());
// })
// ;
// } else {
// this.state = 'ready';
// this.emit('ready');
// }
// }
}
getPlatformName() { return 'odysee'; }
_joinChannelByUsername(channelData) {
let channel = new OdyseeChannel(this, channelData);
channel.id = channelData.claim + '-' + this._generateRandomString(8);
this.channels[channel.id] = channel;
return channel;
}
joinChannel(channelData) {
return new Promise((resolve, reject) => {
if(channelData.claim) {
return resolve(this._joinChannelByUsername(channelData));
} else reject(new Error('No claim specified!'));
});
}
}
if(typeof process === 'object') {
module.exports = OdyseeChat;
}

@ -0,0 +1,110 @@
var WebSocket = require('isomorphic-ws');
var EventEmitter = require('events');
class OdyseeSocket extends EventEmitter {
constructor(config) {
super();
config = config || {};
this.wsUrl = 'wss://sockety.odysee.com/ws/commentron';
this.id = 1;
this.subscriptions = {};
this.queue = [];
// Keepalive
this.expectedPingInterval = config.expectedPingInterval || 20000; // miliseconds
this.reconnectDelay = config.reconnectDelay || 2000;
this.pingTimeout = null;
this.webSocket = null;
}
_sendToWebsocket(json) {
this.webSocket.send(json);
this.emit('verbose', 'SEND ' + json);
}
send(data) {
var json = JSON.stringify(data);
if(!this.webSocket || this.webSocket.readyState != 1) {
this.queue.push(json);
return;
}
this._sendToWebsocket(json);
}
clearPingTimeout() {
if(this.pingTimeout)
clearTimeout(this.pingTimeout);
}
setPingTimeout() {
this.clearPingTimeout();
this.pingTimeout = setTimeout(() => { this.connect(); }, this.expectedPingInterval + this.reconnectDelay);
}
connect() {
let wsUrl = this.wsUrl + '?id='+this.claim+'&category='+this.claim;
console.log('Connecting to WS', wsUrl);
this.emit('verbose', 'Opening WebSocket ' + wsUrl);
this.webSocket = new WebSocket(wsUrl, { headers: { 'Accept-Language': 'en-US,en;q=0.9', 'Origin': 'https://odysee.com'}});
this.webSocket.onopen = (evt) => {
this.emit('verbose', 'websocket open');
this.emit('open');
if(this.queue.length > 0) {
for(let i in this.queue) {
if(this.webSocket.readyState != 1)
continue; // prevent losses
this._sendToWebsocket(this.queue[i]);
}
this.queue = [];
}
};
this.webSocket.onclose = (evt) => {
this.emit('verbose', 'websocket close');
if(this.webSocket)
this.webSocket.onopen = this.webSocket.onclose = this.webSocket.onerror = this.webSocket.onmessage = undefined;
this.webSocket = null;
this.clearPingTimeout();
setTimeout(() => { this.connect(); }, this.reconnectDelay);
};
this.webSocket.onerror = (evt) => {
this.emit('verbose', 'websocket error');
if(this.webSocket)
this.webSocket.onopen = this.webSocket.onclose = this.webSocket.onerror = this.webSocket.onmessage = undefined;
this.webSocket = null;
this.clearPingTimeout();
setTimeout(() => { this.connect(); }, this.reconnectDelay);
};
this.webSocket.onmessage = (ev) => {
this.emit('verbose', 'RECV ' + ev.data.replace(/\s*$/, ''));
var data;
try {
data = JSON.parse(ev.data);
} catch(e) {
this.error('Could not parse JSON', ev.data, e);
}
if(data)
this.handleWebsocketMessage(data);
};
}
isConnected() {
return this.webSocket && this.webSocket.readyState == 1;
}
handleWebsocketMessage(data) {
this.emit('data', data);
}
startStreamMessageSubscription(claim) {
this.claim = claim;
this.connect();
}
}
module.exports = OdyseeSocket;
Loading…
Cancel
Save