this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial setup

alice 7ba278de 039f5155

+163 -29
+4 -3
package.json
··· 30 30 }, 31 31 "dependencies": { 32 32 "@atproto/api": "^0.13.11", 33 - "@skyware/bot": "^0.3.3", 34 - "@skyware/jetstream": "^0.1.8", 33 + "@skyware/bot": "^0.3.6", 34 + "@skyware/jetstream": "^0.2.0", 35 35 "@skyware/labeler": "^0.1.7", 36 36 "dotenv": "^16.4.5", 37 37 "express": "^4.21.0", ··· 39 39 "lint-staged": "^15.2.10", 40 40 "pino": "^9.4.0", 41 41 "pino-pretty": "^11.2.2", 42 - "prom-client": "^15.1.3" 42 + "prom-client": "^15.1.3", 43 + "sharp": "^0.33.5" 43 44 } 44 45 }
+110 -22
src/constants.ts
··· 1 1 import { Label } from './types.js'; 2 2 3 - export const DELETE = 'insert-rkey-of-delete-post-here'; 4 - export const LABEL_LIMIT = 1; 3 + export const DELETE = '3l7rgyic32l2e'; 4 + export const LABEL_LIMIT = 2; 5 5 export const LABELS: Label[] = [ 6 6 { 7 - rkey: 'insert-rkey-here', 8 - identifier: 'earth', 7 + rkey: '3l7rgxxyphl2e', 8 + identifier: 'fise-isfp', 9 + typeinmindUrl: 'https://www.typeinmind.com/fise', 9 10 locales: [ 10 - { lang: 'en', name: 'Earth 🌎', description: 'Earth'}, 11 - { lang: 'pt-BR', name: 'Terra 🌎', description: 'Terra'}, 11 + { lang: 'en', name: 'FiSe (ISFP)', description: 'FiSe (ISFP)'}, 12 12 ] 13 13 }, 14 14 { 15 - rkey: 'insert-rkey-here', 16 - identifier: 'fire', 15 + rkey: '3l7rgxzsi4k2c', 16 + identifier: 'tine-intp', 17 + typeinmindUrl: 'https://www.typeinmind.com/tine', 17 18 locales: [ 18 - { lang: 'en', name: 'Fire 🔥', description: 'Fire'}, 19 - { lang: 'pt-BR', name: 'Fogo 🔥', description: 'Fogo'}, 19 + { lang: 'en', name: 'TiNe (INTP)', description: 'TiNe (INTP)'}, 20 20 ] 21 21 }, 22 22 { 23 - rkey: 'insert-rkey-here', 24 - identifier: 'air', 23 + rkey: '3l7rgy2tueu27', 24 + identifier: 'fine-infp', 25 + typeinmindUrl: 'https://www.typeinmind.com/fine', 25 26 locales: [ 26 - { lang: 'en', name: 'Air 💨', description: 'Air'}, 27 - { lang: 'pt-BR', name: 'Ar 💨', description: 'Ar'}, 27 + { lang: 'en', name: 'FiNe (INFP)', description: 'FiNe (INFP)'}, 28 28 ] 29 29 }, 30 30 { 31 - rkey: 'insert-rkey-here', 32 - identifier: 'water', 31 + rkey: '3l7rgy3ounc2h', 32 + identifier: 'tise-istp', 33 + typeinmindUrl: 'https://www.typeinmind.com/tise', 33 34 locales: [ 34 - { lang: 'en', name: 'Water 💧', description: 'Water'}, 35 - { lang: 'pt-BR', name: 'Água 💧', description: 'Água'}, 35 + { lang: 'en', name: 'TiSe (ISTP)', description: 'TiSe (ISTP)'}, 36 + ] 37 + }, 38 + { 39 + rkey: '3l7rgy4jvxe2f', 40 + identifier: 'nife-infj', 41 + typeinmindUrl: 'https://www.typeinmind.com/nife', 42 + locales: [ 43 + { lang: 'en', name: 'NiFe (INFJ)', description: 'NiFe (INFJ)'}, 44 + ] 45 + }, 46 + { 47 + rkey: '3l7rgy5e4qg2o', 48 + identifier: 'nite-intj', 49 + typeinmindUrl: 'https://www.typeinmind.com/nite', 50 + locales: [ 51 + { lang: 'en', name: 'NiTe (INTJ)', description: 'NiTe (INTJ)'}, 36 52 ] 37 53 }, 38 54 { 39 - rkey: 'insert-rkey-here', 40 - identifier: 'love', 55 + rkey: '3l7rgy674442f', 56 + identifier: 'sife-isfj', 57 + typeinmindUrl: 'https://www.typeinmind.com/sife', 41 58 locales: [ 42 - { lang: 'en', name: 'Love 💞', description: 'Love'}, 43 - { lang: 'pt-BR', name: 'Amor 💞', description: 'Amor'}, 59 + { lang: 'en', name: 'SiFe (ISFJ)', description: 'SiFe (ISFJ)'}, 60 + ] 61 + }, 62 + { 63 + rkey: '3l7rgy7hb7o2a', 64 + identifier: 'site-istj', 65 + typeinmindUrl: 'https://www.typeinmind.com/site', 66 + locales: [ 67 + { lang: 'en', name: 'SiTe (ISTJ)', description: 'SiTe (ISTJ)'}, 68 + ] 69 + }, 70 + { 71 + rkey: '3l7rgyacxve27', 72 + identifier: 'feni-enfj', 73 + typeinmindUrl: 'https://www.typeinmind.com/feni', 74 + locales: [ 75 + { lang: 'en', name: 'FeNi (ENFJ)', description: 'FeNi (ENFJ)'}, 76 + ] 77 + }, 78 + { 79 + rkey: '3l7rgyb6nov2z', 80 + identifier: 'fesi-esfj', 81 + typeinmindUrl: 'https://www.typeinmind.com/fesi', 82 + locales: [ 83 + { lang: 'en', name: 'FeSi (ESFJ)', description: 'FeSi (ESFJ)'}, 84 + ] 85 + }, 86 + { 87 + rkey: '3l7rgycjdwm2f', 88 + identifier: 'teni-entj', 89 + typeinmindUrl: 'https://www.typeinmind.com/teni', 90 + locales: [ 91 + { lang: 'en', name: 'TeNi (ENTJ)', description: 'TeNi (ENTJ)'}, 92 + ] 93 + }, 94 + { 95 + rkey: '3l7rgyebfsg2u', 96 + identifier: 'tesi-estj', 97 + typeinmindUrl: 'https://www.typeinmind.com/tesi', 98 + locales: [ 99 + { lang: 'en', name: 'TeSi (ESTJ)', description: 'TeSi (ESTJ)'}, 100 + ] 101 + }, 102 + { 103 + rkey: '3l7rgyfjwqu2f', 104 + identifier: 'nefi-enfp', 105 + typeinmindUrl: 'https://www.typeinmind.com/nefi', 106 + locales: [ 107 + { lang: 'en', name: 'NeFi (ENFP)', description: 'NeFi (ENFP)'}, 108 + ] 109 + }, 110 + { 111 + rkey: '3l7rgyghptg2a', 112 + identifier: 'neti-entp', 113 + typeinmindUrl: 'https://www.typeinmind.com/neti', 114 + locales: [ 115 + { lang: 'en', name: 'NeTi (ENTP)', description: 'NeTi (ENTP)'}, 116 + ] 117 + }, 118 + { 119 + rkey: '3l7rgyhbey72t', 120 + identifier: 'sefi-esfp', 121 + typeinmindUrl: 'https://www.typeinmind.com/sefi', 122 + locales: [ 123 + { lang: 'en', name: 'SeFi (ESFP)', description: 'SeFi (ESFP)'}, 124 + ] 125 + }, 126 + { 127 + rkey: '3l7rgyi52rs2r', 128 + identifier: 'seti-estp', 129 + typeinmindUrl: 'https://www.typeinmind.com/seti', 130 + locales: [ 131 + { lang: 'en', name: 'SeTi (ESTP)', description: 'SeTi (ESTP)'}, 44 132 ] 45 133 }, 46 134 ];
+48 -4
src/set-posts.ts
··· 2 2 3 3 import { BSKY_IDENTIFIER, BSKY_PASSWORD } from './config.js'; 4 4 import { LABELS } from './constants.js'; 5 + import sharp from 'sharp'; 5 6 6 7 const bot = new Bot(); 7 8 ··· 39 40 threadgate: { allowLists: [] }, 40 41 }); 41 42 42 - const labelNames = LABELS.map((label) => label.locales.map((locale) => locale.name).join(' | ')); 43 + interface Card { 44 + error: string; 45 + likely_type: string; 46 + url: string; 47 + title: string; 48 + description: string; 49 + image: string; 50 + } 51 + 52 + const labelNamesAndUrls = LABELS.map((label) => ({ name: label.locales[0].name, url: label.typeinmindUrl })); 43 53 const labelRkeys: Record<string, string> = {}; 44 - for (const labelName of labelNames) { 45 - const labelPost = await post.reply({ text: labelName }); 46 - labelRkeys[labelName] = labelPost.uri.split('/').pop()!; 54 + for (const label of labelNamesAndUrls) { 55 + const card: Card = await (async (url: string) => { 56 + const res = await fetch(`https://cardyb.bsky.app/v1/extract?url=${encodeURIComponent(url)}`); 57 + return await res.json() as Card; 58 + })(label.url); 59 + const image = await (async (url: string) => { 60 + const res = await fetch(url); 61 + return await res.arrayBuffer(); 62 + })(card.image); 63 + const imageBuffer = await sharp(image).jpeg({ quality: 90 }).toBuffer(); 64 + const imageBlob = new Blob([imageBuffer], { type: 'image/jpeg' }); 65 + const labelPost = await post.reply({ 66 + text: label.name, 67 + facets: [ 68 + { 69 + index: { 70 + byteStart: 0, 71 + byteEnd: label.name.length 72 + }, 73 + features: [ 74 + { 75 + $type: 'app.bsky.richtext.facet#link', 76 + uri: label.url, 77 + }, 78 + ], 79 + }, 80 + ], 81 + external: { 82 + uri: card.url, 83 + title: card.title, 84 + description: card.description, 85 + thumb: { 86 + data: imageBlob, 87 + } 88 + }, 89 + }); 90 + labelRkeys[label.name] = labelPost.uri.split('/').pop()!; 47 91 } 48 92 49 93 console.log('Label rkeys:');
+1
src/types.ts
··· 3 3 export interface Label { 4 4 rkey: string; 5 5 identifier: string; 6 + typeinmindUrl: string; 6 7 locales: LabelValueDefinitionStrings[]; 7 8 }