~zethra/sasha-fetch

ref: 4811fde2c3d77f3e4db12c20a7ba2909205400d1 sasha-fetch/sasha-fetch.py -rwxr-xr-x 3.9 KiB
4811fde2 — Sashanoraa Added README 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3

message = '''
Sashanoraa
----------
Pronouns:   any
Gender:     Non-binary / Gender Queer
Matrix:     @zethra:matrix.org
Email:      ben@benaaron.dev
Mastodon:   @zethra@fosstodon.org
Website:    sashanoraa.gay
Protonmail: sashanoraa@protonmail.com
'''.splitlines()

import sys
import math
import random
import signal
import argparse
from time import sleep

COLOR_ANSI = (
    (0x00, 0x00, 0x00), (0xcd, 0x00, 0x00),
    (0x00, 0xcd, 0x00), (0xcd, 0xcd, 0x00),
    (0x00, 0x00, 0xee), (0xcd, 0x00, 0xcd),
    (0x00, 0xcd, 0xcd), (0xe5, 0xe5, 0xe5),
    (0x7f, 0x7f, 0x7f), (0xff, 0x00, 0x00),
    (0x00, 0xff, 0x00), (0xff, 0xff, 0x00),
    (0x5c, 0x5c, 0xff), (0xff, 0x00, 0xff),
    (0x00, 0xff, 0xff), (0xff, 0xff, 0xff),
)

class TextColor:
    def __init__(self, mode=256):
        self.mode = mode
        self.os = random.randint(10, 25)
        self.spread = 5.0
        self.freq = 0.1

    def _distance(self, rgb1, rgb2):
        return sum(map(lambda c: (c[0] - c[1]) ** 2,
            zip(rgb1, rgb2)))

    def ansi(self, rgb):
        r, g, b = rgb

        if self.mode in (8, 16):
            colors = COLOR_ANSI[:self.mode]
            matches = [(self._distance(c, map(int, rgb)), i) for i, c in enumerate(colors)]
            matches.sort()
            color = matches[0][1]

            return '3%d' % (color,)
        else:
            gray_possible = True
            sep = 2.5
            gray = 0

            while gray_possible:
                if r < sep or g < sep or b < sep:
                    gray = r < sep and g < sep and b < sep
                    gray_possible = False

                sep += 42.5

            if gray:
                color = 232 + int(float(sum(rgb) / 33.0))
            else:
                color = sum([16]+[int(6 * float(val)/256) * mod
                    for val, mod in zip(rgb, [36, 6, 1])])

            return '38;5;%d' % (color,)

    def wrap(self, *codes):
        return '\x1b[%sm' % (''.join(codes),)

    def rainbow(self, freq, i):
        r = math.sin(freq * i) * 127 + 128
        g = math.sin(freq * i + 2 * math.pi / 3) * 127 + 128
        b = math.sin(freq * i + 4 * math.pi / 3) * 127 + 128
        return [r, g, b]

    def apply_color(self, s):
        output = ""
        for i, c in enumerate(s):
            rgb = self.rainbow(self.freq, self.os + i / self.spread)
            output += ''.join([
                self.wrap(self.ansi(rgb)),
                c
            ])
        return output

def generate(args):
    with open('profile') as f:
        img = f.read().splitlines()

    titles = TextColor()
    data = TextColor()
    # Set the data color seed to something far away from the title seed so they look different
    data.os = ((titles.os - 10 + 7) % 15) + 10

    with open(args.output, 'w') as output:
        for (i, m) in zip(img, message):
            if ':' in m:
                parts = m.split(':')
                output.write(f'{i} {titles.apply_color(parts[0])}: {data.apply_color(":".join(parts[1:]))}\n')
            else:
                output.write(f'{i} {titles.apply_color(m)}\n')

        for i in img[len(message):]:
            output.write(i + '\n')

def main():
    parser = argparse.ArgumentParser(description="Generate cool neofetch like card")
    parser.add_argument('output', help='Path to output to')
    parser.add_argument('-d', type=float, help='Run in daemon mode, regenerating output every N minutes')
    args = parser.parse_args()
    if args.d:
        wait_time = int(args.d * 60)
        signal.signal(signal.SIGINT, lambda s, f: sys.exit(0))
        signal.signal(signal.SIGTERM, lambda s, f: sys.exit(0))
        print(f'Generating fetch output in daemon mode every {args.d} minutes')
        while True:
            generate(args)
            sleep(wait_time)
            print('Updating fetch output')
    else:
        print('Generating fetch output')
        generate(args)

if __name__ == '__main__':
    main()