~zethra/sasha-fetch

ref: 77905c868a6873743abf899ac5e9aed23decfc46 sasha-fetch/sasha-fetch.py -rwxr-xr-x 3.9 KiB
77905c86 — Sashanoraa More features 7 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()